Open farskipper opened 7 years ago
Related: #171 think about user-defined KRL operators
Great start for discussion.
option is to drop the .key membership access
I vote to keep maps and arrays separate. You'd basically need to check if a list is an array type for certain operators.
I noticed that the http library docs use ["<key>"]
to access a map value. I don't think this should be supported for maps, because we already have {"<key>"}
, which can include a hashpath.
Related is being consistent on KRL's handling of type errors. I know in the old language and much of the new KRL is weakly typed/does type coercion where possible. However, other places where type coercion doesn't work should we return null or raise a TypeError?
i.e. #201 n.range("-1")
should that try and parse the string to an int first? then what about n.range("foo")
? coerce to 0, return null, or raise an error?
i.e. null + 4
should it be 4
, "null4"
or raise an error?
any stdlib operator can be used on any type. i.e. operators are not behaving like method calls
The iterator functions, for example, could check the type (array or map) and have a different implementation for each, i.e. dynamic dispatch.
And so we could forbid .head()
and .tail()
on maps, which isn't generally catchable at compile time, but we could throw runtime errors.
where type coercion doesn't work should we return null or raise a TypeError?
With the exception of methods like .as()
that explicitly deal with type conversion (so null
sometimes makes sense), I think type errors should be type errors, and implicit coercion should be explicitly documented for the library apis.
Which is how I recommend handling the .range()
case.
Note that KRL's stance on weak typing/implicit coercion still lets us decide what type errors really are unfixable by coercion.
Let's let maps have key ordering in the JS way (and giving more compatibility with arrays)
In light of the map ordering decision, @farskipper would understand the implications of this better than me:
http://blog.caplin.com/2012/01/13/javascript-is-hard-part-1-you-cant-trust-arrays/
I'm not sure about map key order: https://stackoverflow.com/questions/30076219/does-es6-introduce-a-well-defined-order-of-enumeration-for-object-properties/30919039#30919039
><
uses map keys, collection operators use map values; if head/tail works I prefer map values, but I haven't found anything about plain object insertion order in the ES5 spec yet.
Change of plans: KRL will not guarantee map key order or support <map>.head()
or tail
.
@farskipper BTW, I found out about object enumeration in the ECMAScript spec, and Lodash uses it: https://github.com/lodash/lodash/blob/860d1f9484982d45ead630f3ed87ca7d0c5ae2cd/_baseAssignValue.js#L16
However, async makes it sound undependable (or new?).
Right now KRL, stdlib operator functions are treated as syntactic sugar for function calls.
Therefore any stdlib operator can be used on any type. i.e. operators are not behaving like method calls (which is what they look like)
One downside of the current syntax is it looks like you should be able to define your own operator (method) i.e.
One option is to drop the
.key
membership access so that.
is only used for operators.Since operators can be used on any type, the standard library tries to treat values polymorphically where possible (in a half-baked way). For example maps and arrays. Arrays are treated as maps with integer keys.
For example:
So iteration functions take the signature
function(value, key, collection){..}
This is the same for maps and arrays. And even the same for theforeach
on rules wheresetting(value, key)
and you canforeach
over maps or arrays.However, this has not been totally thought through. For example using
.head()
or.tail()
on a map. Should it use values, keys, or key/value pairs?If we just use values, it will be consistent with how iterator functions use the value as the first argument. And if you wanted pairs you could do
foo.pairs().head()
An alternative approach is to treat maps as lists of key value pairs. Instead of treating arrays as maps, treat maps and arrays both as lists. For example:
This is more similar to how clojure treats all collections as all seqs.
Anyways, sorry for the novel. This is just to begin a discussion. I believe thinking through all this will help reduce all the confusion/bugs surrounding the stdlib, and make it quicker to implement it right.