About Monkey 2 › Forums › Monkey 2 Development › Translation hanging with nested struct templates
This topic contains 10 replies, has 4 voices, and was last updated by
AaronK 1 year, 11 months ago.
-
AuthorPosts
-
April 17, 2017 at 3:37 am #7922
Hi all, here’s a minimal test program that duplicates an error I was having last night
Translation hangs
[/crayon]Monkey12345678910111213[crayon-5cba9ba282a07759322993 inline="true" ]Struct FredEndStruct Jim<T>Struct Bob<N>Field b:Bob<N>EndField bob:Bob<T>EndFunction Main()Local j:Jim<Fred>EndApril 20, 2017 at 7:58 am #7975Just to add, if Jim<> was declared as a class, it would build fine.
April 20, 2017 at 10:00 am #7979kill Bob,
Marry Jim
Move in with Mary…
April 22, 2017 at 2:08 am #7987Or even simpler…will fix.
Monkey1234567Struct SField s:SEndFunction Main()EndApril 23, 2017 at 12:47 pm #8021Hi Mark, not sure what you mean. My minimal code was what I needed; that is, nested template structs.
April 25, 2017 at 10:06 pm #8045Sorry, probably should’ve explained a bit better.
Your code has the same problem as my ‘Struct S’ example above, ie: it delcares a type that contains an instance of itself (which therefore contains an instance of itself etc etc). In your case the type is Bob<N> but the idea’s the same. It works when you use a class because a type can of course contain a reference to itself, and classes are ‘reference types’.
The compiler should of course not hang – you should get a ‘recursive type definition’ error or something, be cool if you could add this to github so I remember! – but ultimately your code can’t work as is and will need to change.
April 26, 2017 at 7:56 am #8051Gotcha.
Question. Was there a reason structs are by-value and classes are by-reference as opposed to allowing the user to specify? I find the former is more error prone because the ref/value semantics is not localised; you need to go to the declaration or documentation to find out what it would be and remember it. Having it user specified would make it clear at the point of definition.
I also noticed that there is a Ptr keyword which might solve my problem however I’m not sure how to get the address of an object to set it.
April 26, 2017 at 5:33 pm #8052Hi Aaron we had a talk about Classes VS Structs here.
http://monkey2.monkey-x.com/forums/topic/struct-goofiness/#post-7734In C the concept of reference/value is about how you want to pass your structs into mutator functions. If you pass a struct by value it is made into a copy, but if you pass it by reference it means that you pass the address of the struct – not the actual struct.
In object oriented programming languages it’s something else, it means that objects are something like virtual datatypes which have meaning inside the language runtime, but not 100% direct meaning to the operating system overall. For example in C if you declare an integer it means 4 bytes of memory, but in an object oriented language it means an object that is an integer datatype.
In Monkey i found that if you want to mutate structs you need to do something like this:
Monkey1234567891011121314151617#Import "<mojo>"Using mojo..Struct TypeStructField Test:StringEndFunction ChangeTypeStruct(t:TypeStruct Ptr, message:String)t->Test = messageEndFunction Main()New AppInstanceLocal t := New TypeStructChangeTypeStruct(Varptr t, "Hello")Print(t.Test)EndApril 27, 2017 at 12:51 am #8053Was there a reason structs are by-value and classes are by-reference as opposed to allowing the user to specify?
‘Coz it’s WAY simpler and the alternative opens a pandora’s box of complexity. For starters, people would have to starting tagging many of their variables, parameters, return types etc with ‘ByRef’ or something. I would personally hate this as a user.
There’d be confusion over when to use ByRef, a bunch of technical issues like dereferencing, in place construction, probably GC issues, slicing issues (not currently an issue as structs can’t extend) – all that really *fun* stuff from C++ that makes me want to write new languages!
April 27, 2017 at 9:21 pm #8062In my experience, the fact that the code for a struct instance and class instance looks identical, but behaves differently is potentially dangerous. C++ has it too of course (Although it provides some protection with non reassignment of references) but finding the solution is fast (Look at the function signature) as opposed to having to go to the declaration.
If I had
[/crayon]Monkey12345678[crayon-5cba9ba29c7fa804950136 inline="true" ]Method LogansRun(a:MyThing)If a.age > 29 Thena.alive = FalseEndIf a.alive = False ThenPlaySombreMusic()EndEndThis is contrived of course but what happens on function end? Is a changed or not? My understanding is that a is NOT changed in the caller if it’s a struct, but if it’s a class it is. This is compounded more by the fact that if you later change from struct to class (Maybe you want to extend from something), the program behaves completely differently and you’d likely have to refactor a lot of code. Now there might be solutions in Monkey that solve these issues, I’m still really new to it, but when I see by value/ref based on struct/class it raises some red flags
Without knowing the internals I’m not sure how having it user specified would cause too many problems, it’s just moving the issue from the declaration to the called function which I think is where a user would want to specify certain behaviour. Sure you’d have to have some qualifiers in some case, but maybe making the default case be “by reference” you could reduce the need for it immensely. For instance if everything was by ref by default, potentially one keyword could be used for the other cases
[/crayon]Monkey123456789101112[crayon-5cba9ba29c802034789545 inline="true" ]Method LogansRun(a:MyThing ByValue)If a.age > 9 Thena.alive = falseEndIf a.alive = False ThenPlaySombreMusic()EndLocal b := a ' Obviously by references as that's the defaultLocal c := a.Clone() orLocal c:MyThing ByValue = a orLocal c := Copy aEndIf you hated ByValue maybe if function signature has () that means “construct a new one” as in
[/crayon]Monkey12[crayon-5cba9ba29c808630664027 inline="true" ]Method LogansRun(a:MyThing()) ' Not sure if this is clearer than the one aboveEndAnyway, not trying to be a dick just trying to provide some feedback based on concerns about proneness to errors with the way it currently is.
Cheers
April 27, 2017 at 9:30 pm #8063Thanks for the reply @cocon. I’m very familiar with OO and C++ (I do it for a job), my concern is the potential danger when tying ref/value semantics to the declaration of a type. As I outlined above there’s some potentially very dangerous issues that can arise and I feel the code is less easy to reason about (You need to get back to the declaration). The latter can be solved in some part with a great IDE but TED isn’t there yet.
In your example above, the reasoning is only clearer because you’ve essentially used a variant of Hungarian notation by adding Struct to the type name. I think this is bad form in and of itself, however if the functions were generics, you wouldn’t see that even.
[/crayon]Monkey123456[crayon-5cba9ba2a2ced399288634 inline="true" ]Class Bob<T>Method Grow(t:T, amount:UInt)t.width += amountt.height += amountEndEndDoes completely different things if the ‘t’ passed in was a struct or class. The compiler at present can’t help either as it’s OK to use either struct or class.
I’ve probably belaboured the point
-
AuthorPosts
You must be logged in to reply to this topic.