About Monkey 2 › Forums › Monkey 2 Programming Help › Operator overloading (hello, php)
This topic contains 10 replies, has 4 voices, and was last updated by
cocon 6 months ago.
-
AuthorPosts
-
January 30, 2018 at 5:09 pm #13361
I’m working with PHP last time, and there is a nice array syntax:
arr[] = "hello";
that means append the string to array.
I tried to achive that in Monkey2.
Monkey1234567891011Class ArrOperator[]=( key:String=Null,val:Variant )EndOperator[]:Variant( key:String )EndEndI set default value of key to Null hoping to be able to omit key, but with no luck:
Monkey1arr[] = "hello"result is:
Error : Expecting expression but encountered ']'
It’s impossible, I think, and looks like just as academic try.
January 30, 2018 at 7:34 pm #13364You refer to this one right?
http://php.net/manual/en/function.array-push.phpFrom what I have tested up until now, in Monkey the operator [] as a language construct is specified to work as an indexer (which is similar to a C# concept). http://monkeycoder.co.nz/forums/topic/some-indexers-for-lists/
You can think of the indexer function signatures (if you assume that there is no operators at all) similar to this:
Monkey12Function IndexerOnly<T2>:T1(t1:T1)Function IndexerWithEquals<T1, T2>(t1:T1, t2:T2)Where in this example you can see how this concept would possible work, but be aware that this is only an example for the Joy-Of-API-Hacking and satisfy the compiler.
Monkey123456789101112131415161718192021222324252627282930313233343536#Import "<std>"Using std..Struct SupaStringField TheString:StringOperator[]=(key:Bool, value:String)' normally you would overload the "key" parameter with key:Bool=False' but in this case it's a restriction of the [] operator' that really needs a value inside the [] operatorIf keyTheString += valueElseTheString = valueEndEndOperator[]:String(key:String=False)Return TheStringEndEndFunction Main()Local supa := New SupaStringsupa[False] = "Hello World"supa[False] = "Super Duper" ' false key will replacesupa[True] = " String" ' true key will appendsupa[True] = " Is The Best"Print(supa[False])EndAlso for the record, @hezkore found a way of changing the fundamental datatypes, perhaps you would be interested to see how you can change the meaning of the [] operator with this one, I haven’t tried something like this yet to be sure but it seems interesting.
https://github.com/Hezkore/m2stp/blob/master/inc/base_functions.monkey2January 30, 2018 at 10:07 pm #13369that means append the string to array.
It sure doesn’t look like it!
This would require major changers to the parser though, as ‘[]’ is not a valid ‘value expression’ (it may only appear in type expressions, ie: when declaring the type of something).
How about ‘+=’ instead? This looks much more logical to me.
January 31, 2018 at 4:11 am #13379You refer to this one right?
Yes. Your example is not good enough because I want to omit the key at all.
Also, if you pass False as a string parameter, you’ll get the string “False”, not an empty string,
and expression If key then... always be true.
I think you mean to pass Null here.
How about ‘+=’ instead? This looks much more logical to me.
It seems to be the only way here.
Brackets show us we deal with array, but += don’t.
But I don’t expect to break parser and our minds just because the PHP syntax.
January 31, 2018 at 5:15 am #13381Brackets show us we deal with array, but += don’t.
That’s about all it shows. The syntax ‘[]=’ to append to an array is typical php WTF-ness!
But I did have a quick look at the parser and, I sort of hate to say it, but it’s actually a pretty simple tweak to allow no args for array indexing. With a 2 line change to parser.monkey2 I can compile this…
Monkey123456789101112131415161718192021Class COperator[]=( key:String,value:String )Print "key="+key+", value="+valueEndOperator[]=( value:String )Print "value="+valueEndEndFunction Main()Local c:=New Cc["one"]="two"c[]="Hello there!"End…which isn’t quite what you wanted, but enough to be able to do what you want I believe?
I still really dislike []= to append to an array though, boring old Method Add() is IMO a much better option!
January 31, 2018 at 6:16 am #13384Wow, good news!
When you omit key it passes as Null ?
January 31, 2018 at 8:36 am #13386That’s about all it shows. The syntax ‘[]=’ to append to an array is typical php WTF-ness!
I agree. += is nice though.
October 11, 2018 at 2:24 pm #15521I’m thinking about assignment operator, again
And it would be enough for me to have []= operator as a special kind of assignment.
Monkey1234567891011121314151617181920212223242526272829Function Main()Local t:=New Test<Float>' special kind of assignment' equals to t.value=3.0t[]=3.0' special king of return value' equals to 10+t.valueLocal sum:=10+t[]Print t.valueEndClass Test<T>Field value:TOperator []=( value:T )Self.value=valueEndOperator []:T( i:Int=0 )Return Self.valueEndEndThis time both of these operators don’t work.
and this sounds interesting:
With a 2 line change to parser.monkey2 I can compile this
What are anyone think about it?:)
As for me – it could be a part of language, we don’t need to use it every time…
October 13, 2018 at 3:06 am #15523Yeah, nah…
Sorry, but it still looks kind of nasty to me. And aren’t you gonna confuse a whole bunch of php users?!?
I’m probably not quite as adverse to overloading ‘=’ as I used to be though. I assume the goal here is still to achieve ‘property changed’ events/signals?
I mean, you can already do this quite easily:
Monkey12345678910111213141516Class MyLifeField LifestyleChanged:Void()Property Lifestyle:Int()Return _lifestyleSetter( lifestyle:Int )If lifestyle=_lifestyle Return_lifestyle=lifestyleLifestyleChanged()EndPrivateField _lifestyle:IntEnd…but of course you know this! If the goal is to wrap both the signal and the setter/getter in a single concept, you can do this too, eg:
Monkey1234567891011121314151617181920212223242526Struct MyProperty<T>Field Changed:Void()Method Set(value:T)If value=_value Return_value=valueChanged()EndMethod Get:T()Return _valueEndPrivateField _value:TEndClass MyLifeField Lifetyle:MyProperty<Int>EndThis is effectively what your (mostly) doing above, except you need to use Lifestyle.Set() and Lifestyle.Get() to set/get the value, plus you can listen for changes using Lifestyle.Changed+=Lamba…
IMO, the []= syntax isn’t enough of an improvement over plain Set and Get here to justify it. In fact I’d argue Get and Set is much clearer than an ‘array looking’ operator. And either way, the programmer has to ‘know’ to use it (if you see what I mean).
Overloading ‘=’ is much more interesting though – it means ‘live’ properties like this could be added to existing code without user code knowing it wasn’t just reading/writing files/properties. But for this work, there’d also have to be a ‘conversion’ operators for reads. Perhaps something like:
Monkey1234567891011121314151617181920212223242526Struct MyProperty<T>Field Changed:Void()Operator Setter( value:T )If value=_value Return_value=valueChanged()EndOperator Getter:T()Return _valueEndPrivateField _value:TEndClass MyLifeField Lifetyle:MyProperty<Int>EndBut alas we’ve already hit our first complication! If the ‘type’ of Lifestyle is Int thanks to its getter operator, how can we access Lifestyle.Changed?
And if T is a class/struct, what does Lifestyle.blah mean? Is it a member of Lifestyle, or a member of LifeStyle.Getter? The compiler could attempt to guess what you want to do, but it’d likely result in a bunch of confusing rules, and type conversions would be a nightmare when calling functions, assigning to vars etc. And what happens with prop1=prop2? If they are both Int Getters of the same type, should it get/set the int, or assign the entire getter, ‘Changed’ listeners and all? The sensible thing to do in all these cases is probably to treat any value with a Getter as a value of the Getters type instead (just like properties), and add new syntax to somehow ‘ignore’ the getter when you want work with the actual property-like container.
All in all it’s an interesting idea and I think it could be made to work, will keep thinking about it….
October 13, 2018 at 12:34 pm #15524And aren’t you gonna confuse a whole bunch of php users?!?
agree, it’s very bad idea.
If the ‘type’ of Lifestyle is Int thanks to its getter operator, how can we access Lifestyle.Changed?
yes! it’s looks impossible, and I miss it in my minds, if we have getter that return any type – we cant easily access to our parent type,
the way via casting is not what we want.
And what happens with prop1=prop2? If they are both Int Getters of the same type, should it get/set the int, or assign the entire getter, ‘Changed’ listeners and all? The sensible thing to do in all these cases is probably to treat any value with a Getter as a value of the Getters type instead (just like properties), and add new syntax to somehow ‘ignore’ the getter when you want work with the actual property-like container.
I expected to have type conversion for expressions with our type, but not for dot access case, but I see now that it’s kind of impossible.
Even if we’ll have assignment operator we’ll have no proper get operator and need to write getter explicitly:
Monkey123Local prop:=New Property<String>prop="hello"Local s:=prop.Value ' or prop.Get()Operator To:T can help in some cases but not all.
And I think now that using explicit prop.Value for setter and getter is the best solution.
Thanks for the detailed answer, Mark!
October 18, 2018 at 11:58 am #15527Something else theoretical, if we had the ability to declare custom operators as in Haskell, we would simply use them in interesting ways.
As for example let’s say we would like to have the initial idea of nerobot to append strings. We would write this pure function, “pure” means that the function is stateless (state-independent).
Monkey123Function AppendString:String(from:String, to:String)Return from + toEndOK, we might consider that this code is dump pointless
. Now taking concept further we would avoid this once and for all and use this instead.
123456789101112This is the type signature.(+++) :: String -> String -> StringAnd now here in MonkeyHaskellhere is the function declaration.
Function (+++) : String(a:String, b:String)Return a + bEndAnd then we would use the custom operator, either as Prefix (before terms) notation or Infix (inbetween terms)(+++) "Hello" "Monkey""Hello" (+++) "Monkey"The general idea of using custom operators is to reduce “verbose” syntax. Instead of having a pumped API that makes you bored to hell to use it. You would cleverly create important domain operations and thus create such shortcuts.
-
AuthorPosts
You must be logged in to reply to this topic.