Nim: Make procvar default

Created on 20 Feb 2015  Â·  30Comments  Â·  Source: nim-lang/Nim

In order to improve Nim's functional programming support we should make {.procvar.} the default for all procs. Also we need to figure out how to make + work in map and the like.

Feature

Most helpful comment

Yes.

All 30 comments

+1, It would be a logical decision.

Restricting procvar by default also restricts end users from aliasing most procs.

It's often inconvenient, and I was thinking about opening this issue myself.

Just to be clear, this is about procvars, not closures, right? Closures have an extra pointer that points to their environment.

@Varriount yes

@edge "Restricting procvar by default also restricts end users from aliasing most procs."

That was _exactly_ the feature we were after as we like the freedom to introduce new optional parameters in the stdlib.

I (still) don't quite get how requiring the procvar pragma allows adding additional default parameters.

This is causing problems again and again. Would be really nice to be able to just do this:

let
  xs = @[1,2,3,4,5]
  ys = xs.map(`$`)

In this case it's not quite that simple. Since $ is magic, we would need a helper proc around it as the procvar.

@Varriount there was a discussion on irc yesterday about {.procvar.} that among other things answers your question. See from 18:07:56 until 22:19:58: http://irclogs.nim-lang.org/03-04-2015.html

The general consensus seems to be that it would be good to have the compiler generate overloads to the function with optional arguments on-demand.

@Araq So, the solution for this is to have the compiler auto-generate wrapping procedures?

@Varriount auto-warping sounds fishy to me.

@reactormonk Well yes, warping procedures would imply a great deal of fishyness ;D

Seriously though, it would only be doing what users already do when they want to use a procedure that can't be implicitly converted to a procvar.

The best solution would be a type conversion from proc (s: string, def: int = 0): seq[string] to proc (s: string): seq[string]. Maybe with a few heuristics.

And that type conversion would have to be done (at least for the C/C++ backend) by wrapping the original procedure. The C/C++ backends implement default parameters by passing in default values at the call sites. This means that in order to a proc foo(a:int, b=7) to a variable expecting a proc (a:hint) , foo must be wrapped.

The best solution would be a type conversion from proc (s: string, def: int = 0): seq[string] to proc (s: string): seq[string]. Maybe with a few heuristics.

Could that be done simply by wrapping the proc in a closure?

@dom96 You don't even need a closure (since the wrapper doesn't need to capture the surrounding environment).

@Varriount, @ReneSac , @reactormonk - I think the automatic wrapper instantiation of procs for procvar use-sites, based on the use-site's needed sub-set of arguments is perfectly reasonable.

As mentioned, formal parameters with optional arguments, are implemented as "auto-fillins" at call-site. The wrapping is _basically_ no different from that, albeit wrapping the expansion with new formal parameters (ofc. the additional call _if not inlined_). As @Varriount says: one would simple put a lambda expression (import future..) at use site and do the exact same thing manually.

The wrapped function could just be inlined (aka duplicated, in this case): type compat is reached, and no performance is lost. Or better and simpler yet: just leave it to backend to do eventual inlines, and save on compilation time instead, by just making a simple wrapper.

Personally I use functional style a lot on sequences and the like - _in "setup'ish" code_ - never in hot-loop code, where I stick to "good ole" imperativism. So while dev'ing, non-inlined wrappers would be favourable in my eyes.

@dom96 , @edge, @Araq - This would of course by extension, make it reasonable and logical to make procs procvar by default _and_ allow non breaking additional opt. args - and so solve all goals mentioned.

Well, ofc. procvar would sort of lose its meaning...

I'd be totally fine with tossing procvar out.

I like the sound of that! And then auto-wrapping, or rather, auto-instantiations (wider subject: opt-arg-proc-wrappings, tpl's, machine-ops, etc.) is a necessity (a welcome such ;). How hard would this be to implement? Perhaps just opt-arg-proc-wrappers at a first? I've only glanced at the compiler still (I'm still learning the lang), but I know the parsing stage is separated into several passes, so the compiler design appears good to me for not making such a thing tooo hard?? And how does it play out with C* interoperability?

Little _personal_ seconding of general opinion I'd like to add: I agree it's far from a priority to fix (as is already labeled) and could easily be postponed to "post 1.0" (it would then be one of those welcome, "Wow! It got even fucking better!" things for stable adopters), since it is easily and quickly solvable manually atm.
(Meta-question: Is there a label for issues for 'post-1.0-ok"? It would make it easier to pick issues to work on when I get to that stage of nim grokness. So one can focus on getting all core and possibly breaking changes done first. - or does 'low pri' simply imply that? Sorry if it's a stupid question and OT)

Some more discussion about this here http://irclogs.nim-lang.org/15-09-2016.html (starting at ~18:10).

Changing the priority because I think this needs to happen before 1.0.

With 0.17 out, we don't need {.procvar.} anymore right?

We still can't pass built-ins around to map and the like though.

proc foo[T](a: T,
          b: T,
          f: proc(x: T, y: T): T): T =
  return f(a,b)

let a = 11
let b = 10

let z = foo(a,b,`+`)

echo z

@mratsim I thinks even the news mention this. + is mostly a CPU instruction, not a function you can pass around and eventually the compiler will rewrite it to proc (a, b: int): int = a+ b for you, but right now you can do the same.

Not required for v1 at all, plenty of languages live without this feature.

Hrm, I dunno. I'll need to investigate what is possible and what isn't. I don't want FP-lovers to disregard Nim because of this.

Any update on this?

Hrm. Thanks for the ping. Will look into it again when I get home.

On 18 Feb 2018 15:42, "Lloyd Moore" notifications@github.com wrote:

Any update on this?

—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
https://github.com/nim-lang/Nim/issues/2172#issuecomment-366524865, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAPDe-MRGeEIo-iNEQ2bLPFvTuZkEumqks5tWETdgaJpZM4DjCxQ
.

So the question is: will this be a breaking change?

If not then we can postpone this after v1. @Araq is it a breaking change?

So the question is: will this be a breaking change?

Code that currently does not compiles will compile. A strict extension of Nim, not a breaking change.

procvar is gone, closing.

Does that mean it's now default?

Yes.

Was this page helpful?
0 / 5 - 0 ratings