Playing with first class functions

About Monkey 2 Forums Monkey 2 Programming Help Playing with first class functions

This topic contains 19 replies, has 5 voices, and was last updated by  nerobot 1 year, 4 months ago.

Viewing 15 posts - 1 through 15 (of 20 total)
  • Author
    Posts
  • #12051

    nerobot
    Participant

    I was interested in – what will we get from map[key] if map’s value type is a function and map doesn’t contain key?

    The answer is: We’ll get new first-function instance (or what is name for it?).

    Just for experimenting I created NamedEvents class which allow us to subscribe and to emit events by key.

    Shortly:

    And there is a buildable demo showing how you can use it – with String-ed key and with Enum-ed key:

     

    We can create any events by passing different keys.

    I don’t know can it be useful in real life. 🙂

    #12052

    nerobot
    Participant

    It’s like a magic – we don’t put value into Map, but it however is there!

    #12056

    Mark Sibly
    Keymaster

    Very cool!

    It’s like a magic – we don’t put value into Map

    The magic here is thanks to this code…

    …being converted by monkey2 to…

    For the first line, since the map doesn’t actually contain “walk”, a null value is returned by evt[“walk”].

    A null function value is a NOP function (ie: it doesn’t do anything and returns ‘null’) but is still a normal, valid function (just like a null int, ie: 0, is a normal int) and can therefore be used with ‘+’.

    The last line is what actually puts the value into the map – magic!

    #12058

    Amon
    Participant

    That’s pretty cool. Mark Sibly is the Gandalf of Sophisticated Basic Compiler Design. 🙂

    #12059

    Mark Sibly
    Keymaster

    Hopefully it all makes sense though – that is my goal!

    #12070

    nerobot
    Participant

    A null function value is a NOP function (ie: it doesn’t do anything and returns ‘null’) but is still a normal, valid function (just like a null int, ie: 0, is a normal int)

    Returning ‘null’-values of different types can be very insidious.

    For example, С# have method bool TryGetValue( key, out value ) to avoid returning unexisting values, and indexing operator throw an exception if key not found (msdn).

    IMO, for monkey2 will be good at least to improve docs for Map::Get() method and Map::[ ] operator, where would be explained that *you always get ‘default-null’ value here*. And very important to use Map::Contains() if you want to know has map a key of not.

    Have Int(0) isn’t the same as have no value at all.

    Just to pay attention on it.

    #12075

    Ethernaut
    Participant

    That’s really neat, thanks!

    I feel like I still don’t take full advantage of first class functions, even though I understand how they work now. It’s a constant exercise of getting used to new design patterns. Probably good for my brain, though!

    #12076

    abakobo
    Participant

    Here’s is some (more) discovery of undocumented behaviour..

    Is it expected behaviour?

    #12077

    abakobo
    Participant

    and passing by reference could be useful in some designs!

    #12078

    abakobo
    Participant

    Gandalf of Sophisticated Basic Compiler Design.

    I found a new name that would fit fine with google search!

    MOINOBA (MOnkey Is NOt BAsic) (erm just joking …)

    #12079

    Mark Sibly
    Keymaster

    Returning ‘null’-values of different types can be very insidious.

    You’re probably right, although it does allow the above ‘magic’ to work. Ditto other tricks like non-intrusive ref counting, eg: ‘_refs[obj]+=1’ will ‘just work’.

    I’m not really opposed to changing it so that [“blah”] where “blah” is not in the Map causes a runtime error instead. I doubt it’ll cause many/any problems in existing code, but it will break the code at the top you were initially so happy about! Will think about it…

    I feel like I still don’t take full advantage of first class functions, even though I understand how they work now

    I’m a bit the same way, still learning a lot of this stuff. I do think ‘signals’ (ie: ‘Field Changed:Void()’ style members) are often a way better way to go than virtual methods in many situations.

    Is it expected behaviour?

    Almost, you’re definitely supposed to be allowed to chain functions together, although ‘f=f+F2’ should work too, will fix!

    and passing by reference could be useful in some designs!

    I do have a safer ‘Var’ feature on an internal language features todo list…

    #12084

    nerobot
    Participant

    Almost, you’re definitely supposed to be allowed to chain functions together, although ‘f=f+F2’ should work too, will fix!

    I’m not sure that f=f1+f2 is a good idea.

    If f1 returns 5 and f2 returns 10 then f1+f2 should return 15. But in our case we get resulting value of the last call only.

    But operator += is used as ‘subscription’ operator for a long time and it’s behavior is quite expected.

    #12086

    Mark Sibly
    Keymaster

    If f1 returns 5 and f2 returns 10 then f1+f2 should return 15.

    Nothing is being invoked though and IMO, f+=f1 should ‘mean’ the same as f=f+f1, regardless of the types of f and f1.

    operator += is used as ‘subscription’ operator for a long time

    Bah! I hate this ‘reasoning’ for adopting something! To me, ‘+=’ only makes sense because it is possible to ‘add functions’ in the first place with ‘+’ (well, it’s supposed to be…). So there is no ‘subscription’ operator, there is just function addition and ‘+=’ is just an assignment shortcut like all the other forms of ‘+=’.

    #12089

    nerobot
    Participant

    You’re probably right, although it does allow the above ‘magic’ to work. Ditto other tricks like non-intrusive ref counting, eg: ‘_refs[obj]+=1’ will ‘just work’.

    There is an default (t) in c#, don’t know is it possible/ okay for monkey.

    With that mechanism we can write

    GetValue <T>:T ( key:String,value:T=default (T) )

    And it can also create default first class function for us.

    #12090

    Mark Sibly
    Keymaster

    > There is an default (t) in c#

    This is pretty much ‘Null’ in monkey2, eg:

    should be about equivalent (as long as type of ‘T’ can be determined of course).

    This is largely why I made Null ‘context sensitive’ (again – it was in bmx, I goofed in monkey1) – so that generic methods etc. could ‘Return Null’ and so on without caring what type was being returned.

    Indeed, in monkey1 containers there is some awful code like:

    Just to get the same behaviour you can now get in monkey2 from ‘Return Null’! You learn more from your mistakes than your successes etc.

Viewing 15 posts - 1 through 15 (of 20 total)

You must be logged in to reply to this topic.