class List
{
V first()
V last()
V peek()
V pop()
L push(V item)
L sort(|V a, V b->Int| c := null)
L reverse()
L swap(Int indexA, Int indexB)
}
class Map
{
Bool containsKey(K key)
K[] keys()
V[] values()
}
Having the generics for things like Map.keys works out really nice. My current thoughts for the utils on List are that they always occur in-place and return this. That seems a good conceptual model that is easy to remember - then you don't pay the penalty if want it in place, and if you really want another list you can do something like list.dup.sort (also then you can't forget to assign the return value and wonder why your sort, reverse, etc didn't work).
However if we follow the rule that all List utils work in place, then I think there is converse rule that if you use operator shortcuts - you always return a new value. I think it would be weird to have x + y have a side effect on x. Because of that I think it is probably best to avoid use of operator shortcuts with Lists since (other than get and set of course). So I will probably have union() instead of pipe().
I think this test case for for Map.keys and Map.lists sums up how much I love Fan (I had to sort since map doesn't keep the order):
List
{
V find(|V item, Int index->Bool| c)
L findAll(|V item, Int index->Bool| c)
List collect(List acc, |V item, Int index->Obj| c)
}
Map
{
V find(|V value, K key->Bool| c)
M findAll(|V value, K key->Bool| c)
}
brianThu 23 Mar 2006
More good stuff to make List a "humane" API:
List
{
V remove(V item)
V removeAt(Int index)
L trim()
Void eachr(|V item, Int index| c)
L exclude(|V item, Int index->Bool| c)
Bool any(|V item, Int index->Bool| c)
Bool all(|V item, Int index->Bool| c)
V min(|V a, V b->Int| c := null)
V max(|V a, V b->Int| c := null)
L unique()
L sortr(|V a, V b->Int| c := null)
Str join(Str separator := "")
}
brianThu 23 Mar 2006
I added basic support for range literals and slicing. Basically if the type of a [] operator is a range then it maps to slice(), otherwise it maps to get().
Ruby seems a bit sloppy on index checking - sometimes it lets you get over index, sometimes returns nil. I think I agree with John that any out of bounds index will result in a exception. Andy do you have an opinion?
I implemented Range as normalized as inclusive, and ... non-inclusive by appending a decrement operation to the end index. For example [0..3] -> [0..3-1] or [0..-1] -> [0..-1-1]. That actually works in every case but the boundary case of [0...0] -> [0..-1]. So I think I have to break down and add an inclusive/exclusive flag to sys::Range.
andyThu 23 Mar 2006
An exception seems safest. I thought we were going to do the .. and ... for inclusive/exclusive?
brianThu 23 Mar 2006
I did do the .. and ... - that's what I was talking about, although my niave implementation just subtracts one for exclusive which doesn't work when the end index is 0.
brian Sat 18 Mar 2006
I added oodles of new methos to List and Map:
Having the generics for things like Map.keys works out really nice. My current thoughts for the utils on List are that they always occur in-place and return this. That seems a good conceptual model that is easy to remember - then you don't pay the penalty if want it in place, and if you really want another list you can do something like list.dup.sort (also then you can't forget to assign the return value and wonder why your sort, reverse, etc didn't work).
However if we follow the rule that all List utils work in place, then I think there is converse rule that if you use operator shortcuts - you always return a new value. I think it would be weird to have x + y have a side effect on x. Because of that I think it is probably best to avoid use of operator shortcuts with Lists since (other than get and set of course). So I will probably have union() instead of pipe().
I think this test case for for Map.keys and Map.lists sums up how much I love Fan (I had to sort since map doesn't keep the order):
Try writing that test case in Java!
brian Tue 21 Mar 2006
I added support for more closure based iterators:
brian Thu 23 Mar 2006
More good stuff to make List a "humane" API:
brian Thu 23 Mar 2006
I added basic support for range literals and slicing. Basically if the type of a
[]
operator is a range then it maps to slice(), otherwise it maps to get().Ruby seems a bit sloppy on index checking - sometimes it lets you get over index, sometimes returns nil. I think I agree with John that any out of bounds index will result in a exception. Andy do you have an opinion?
I implemented Range as normalized as inclusive, and ... non-inclusive by appending a decrement operation to the end index. For example
[0..3] -> [0..3-1]
or[0..-1] -> [0..-1-1]
. That actually works in every case but the boundary case of[0...0] -> [0..-1]
. So I think I have to break down and add an inclusive/exclusive flag to sys::Range.andy Thu 23 Mar 2006
An exception seems safest. I thought we were going to do the .. and ... for inclusive/exclusive?
brian Thu 23 Mar 2006
I did do the .. and ... - that's what I was talking about, although my niave implementation just subtracts one for exclusive which doesn't work when the end index is 0.