Prim-Lang / Prim

Tooling for using Prim - a safe subset of Nim
Mozilla Public License 2.0
1 stars 0 forks source link

Array Handling #1

Open bbarker opened 4 years ago

bbarker commented 4 years ago

Mutable arrays are quite beneficial - even Haskell uses them (see Vector).

Assuming var parameters aren't used, Nim already guarantees the returned value will be immutable in Prim (since in Prim, we disallow var). But in order to achieve this, array modification functions might benefit from having a special effect that allows for var to be used in a func/proc just for arrays:

func modifyArray[I,T](arr: array[I,T]): array[I,T] {. primVarArray .} =
  var mArr = arr
  ...
  mArr

In this case, modifyArray might be a sort function for instance.

But what if we want to sequence several modification functions together?

See https://github.com/nim-lang/RFCs/issues/226#issuecomment-629760898 for ideas.

bbarker commented 4 years ago

func makeRefArray[I,T](initArray: array[I,T]): ref array[I,T] =
  var refArr: ref array[I, T]
  new(refArr)
  refArr[] = initArray
  refArr

# We can't assign to a normal let-array
# let myArr = [1,2,1]
# myArr[1] = 5

# But we can assign to a refArray
let myRArr = makeRefArray([1,2,1])
myRArr[][1] = 5
echo myRArr[]

# Unfortunately we can also do this
myRArr[] = [3,3,3]
echo myRArr[]

Maybe a better approach would be to make a ref object and overload [] to allow setting on that, then I think you would have an array where individual indices could be altered but the entire array couldn't be assigned to. Better yet, I think i could use distinct so that set ([]) only works on the distinct type.

Then we could have freeze/thaw operations that cast between the distinct types.

Edit: This object ref approach seemed somewhat successful: https://gist.github.com/bbarker/903ff7608e20bdcac09656b2803fa76c

bbarker commented 4 years ago

Also see tensor example at https://github.com/SimonDanisch/julia-challenge/blob/master/nim/nim_sol_mratsim.nim#L8-L68

<FromDiscord> <mratsim> what are you working on @bebarker?
<bebarker> mratsim, just trying to prototype a simple API for converting between immutable and mutable arrays (freeze and thaw)
* couven92 has quit (Ping timeout: 256 seconds)
<bebarker> mratsim, that code you shared was already helpful, realized i need to implement []=
* couven92 (~fredrikhr@2a02:2121:28c:e8e3:953c:c85b:e84a:2399) has joined
* JustASlacker has quit (Ping timeout: 256 seconds)
<FromDiscord> <mratsim> I yes I remember using haskell vectors
<bebarker> mratsim, yeah that was sort of what I had in mind, though not trying to reproduce it 100%
<FromDiscord> <mratsim> here you go: https://github.com/numforge/laser/blob/master/laser/tensor/datatypes.nim#L12-L14
<FromDiscord> <mratsim> and: https://github.com/numforge/laser/blob/master/laser/tensor/datatypes.nim#L104-L111
<FromDiscord> <mratsim> this was to allow safe pointer accesses
<bebarker> mratsim, oh and hi - thanks for your comment on github issues, just haven't had a chance to digest it all yet
<FromDiscord> <mratsim> so when taking a pointer of a tensor, if it was mutable you get a RawMutablePtr with []= defined
<FromDiscord> <mratsim> and if it was an immutable tensor, you get a pointer that prevents you from mutating the data
<FromDiscord> <mratsim> though one thing I can't do yet is preventing the user from escaping with the pointer if the tensor was only local
<FromDiscord> <mratsim> that would need some escape analysis
<FromDiscord> <mratsim> i.e. t's a poor man's write tracking system: https://nim-lang.org/araq/writetracking.html
* Vladar (~Vladar@46.162.2.53) has joined
<FromDiscord> <dom96> did the person that wrote the Julia Challenge ever write up a follow up to declare the winner?
<FromDiscord> <mratsim> I don't think so, maybe there is a wrapup on Reddit or Hacker news or the julia forum
<FromDiscord> <mratsim> for example there is a huge Nim thread on Julia forum: https://discourse.julialang.org/t/version-1-0-released-of-nim-programming-language/29099/47
<bebarker> mratsim, I tried doing this, which seems to work as expected (haven't tested the last note on line 39): https://gist.github.com/bbarker/903ff7608e20bdcac09656b2803fa76c#file-makerefarray-nim-L22-L41
<bebarker> not sure of the performance implications of wrapping an array in a ref object though
<FromDiscord> <mratsim> it depends, if you do that in a loop, it's bad
* audiofile (~notanaudi@unaffiliated/audiofile) has joined
<FromDiscord> <mratsim> if it's once before heavy processing it's the same as stack
bbarker commented 4 years ago

Also regarding in-place vs return copy, see the dup macro

<FromDiscord> <mratsim> the main question with ref array is whether you want separate copies on assignment or if you want assignement to share the same data
* go|dfish has quit (Remote host closed the connection)
<bebarker> mratsim, yeah i've been thinking of that as well - a way to compose mutable operations on an array for instance
<bebarker> well, i haven't thought about it much yet! I should say i need to think about it
<FromDiscord> <mratsim> did you read about the `dup` macro?
* go|dfish (goldfish@nat/dcunetworkingsociety/x-lbjgvrnzjolsygcp) has joined
* Satomi-Kowa (b52e54d0@gateway/web/cgi-irc/kiwiirc.com/ip.181.46.84.208) has joined
<FromDiscord> <mratsim> See https://nim-lang.org/blog/2020/04/03/version-120-released.html grep for "dup"
<bebarker> mratsim, i had the sugar page open just now and saw it when you mentioned it - nice