Re: REPL semantics

2018-07-16 Thread aliak00 via Digitalmars-d

On Thursday, 12 July 2018 at 22:17:29 UTC, Luís Marques wrote:

On Thursday, 12 July 2018 at 21:51:18 UTC, aliak wrote:
Cool, is there on going work to sprucing up the D repl in the 
dlang-community repo or is this a new attempt? Either way if 
something is happening here then awesome!


Ah, that explains why my clone of drepl didn't compile: it was 
the Martin Novak's repo, not the D community one. Although on 
macOS it still doesn't compile, because of the lack of 
_rt_loadLibrary.


Regarding your question: I was investigating this as part of my 
own D-related compiler efforts (DHDL stuff), but it won't 
materialize into a D repl anytime soon. I actually never tried 
the existing REPLs, what are your issues with them?


Ah I see. Last I remember it was just too buggy to use so it 
caused more pain than pleasure :p I don't remember the exact 
details though sorry.




As for your question, hard to say me thinks. On the one hand, 
being able to do this is nice:


const int i = 3;
const int j = 4;
void complexCalculation() { use i and j }
complexCalculation() // uses 3 and 4
const int j = 5;
complexCalculation // uses the new j

On the other hand being able to redefine the name "j" as some 
other type to use in some other computation without having 
`complexCalculation` get messed up is also nice :)


I hadn't even considered *redefining* symbols, only 
overloading. cling doesn't support redefining. Mmmm...



Which is how the swift repl works:

  1> func f(_ a: Float) { print("f") }
  2> f(3)
f
  3> func f(_ a: Int) { print("i") }
  4> f(3)
i
  5> func foo(_ a: Float) { print("f") }
  6> func bar() { print(foo(3)) }
  7> bar()
f
  8> func foo(_ a: Int) { print("i") }
  9> bar()
f


Yeah, I had tried basically the same Swift example. But my 
point stands: I think that behavior can be explained by ease of 
implementation. Finding an example of the alternative would be 
much more interesting. Lacking that we are going to have to 
actually *think* about the problem ;-)


The examples with the dynamic languages are less relevant.


We can try and think:

So if we think of adding an overload as "redefining a name" then 
is it fair to generalize the question to: "should redefining 
symbol A affect any previously defined symbol B that was 
dependent on the previous definition of A?"


And then I'd say that defining an overload of symbol A is 
technically a redefining of A - i.e. it's semantics change.


Redefinition affects:
+ Can change functionality of B without having to redefine all of 
it
- Can cause things to stop working silently (think a tree of 
hidden dependencies)


Redefinition does not affect:
+ The last defined symbol works "as expected"
- Must redefine symbols if you want them to use redefined 
dependent definitions.


I think changing the value of a variable should affect any 
dependent definitions, while redefining a variable should not 
affect dependent symbols - an appeal to predicability is what I'm 
going for.


And I think defining an overload falls under redefining a symbol.

Or you can also have the best of both worlds if you allow a 
special repl annotation before any definitinons - @dynamic on 
symbol A can mean that redefining it will affect dependent 
Symbols for e.g.


Haskell's GHCi repl does the same as swift (with redefining 
symbols at least, don't think it supports overloading in the 
imperative language sense of the term). Though I think that makes 
the most sense for haskell being a pure language.


Cheers,
- Ali



Re: REPL semantics

2018-07-13 Thread Luís Marques via Digitalmars-d

On Friday, 13 July 2018 at 16:55:27 UTC, Seb wrote:

Did you try the Docker image?


No, I just ran it on my Ubuntu VM. Is it important that I try? I 
was just providing feedback that it doesn't seem to run with LDC 
either.




Re: REPL semantics

2018-07-13 Thread Seb via Digitalmars-d

On Friday, 13 July 2018 at 16:20:03 UTC, Luís Marques wrote:

On Friday, 13 July 2018 at 06:22:41 UTC, Jacob Carlborg wrote:

On Friday, 13 July 2018 at 02:26:28 UTC, jmh530 wrote:


No Windows support.

For drepl:
"Works on any OS with full shared library support by DMD 
(currently linux, OSX, and FreeBSD)."


For macOS that means using LDC.


It doesn't seem to work with LDC on macOS either:

$ dub --compiler=ldc2
(...)
Undefined symbols for architecture x86_64:
  "_rt_loadLibrary", referenced from:
  __D4core7runtime7Runtime__T11loadLibraryZQoFxAaZPv in 
drepl.o

ld: symbol(s) not found for architecture x86_64


Did you try the Docker image?


Re: REPL semantics

2018-07-13 Thread Luís Marques via Digitalmars-d

On Friday, 13 July 2018 at 06:27:08 UTC, Jacob Carlborg wrote:
Have you considered using LDC and JIT? [1] [2]. Found this [3] 
snippet as well, not sure what it is.


[1] https://github.com/ldc-developers/ldc/pull/2293
[2] https://github.com/ldc-developers/ldc/releases/tag/v1.8.0 
(mentions something called EasyJIT)

[3] https://gist.github.com/eldar/2294388


I just wanted to know what the REPL semantics were, not so much 
actually use the REPL day to day. For my DHDL stuff I don't think 
the LDC JIT particularly applies, it's more source code 
translation stuff.


Re: REPL semantics

2018-07-13 Thread Luís Marques via Digitalmars-d

On Friday, 13 July 2018 at 06:22:41 UTC, Jacob Carlborg wrote:

On Friday, 13 July 2018 at 02:26:28 UTC, jmh530 wrote:


No Windows support.

For drepl:
"Works on any OS with full shared library support by DMD 
(currently linux, OSX, and FreeBSD)."


For macOS that means using LDC.


It doesn't seem to work with LDC on macOS either:

$ dub --compiler=ldc2
(...)
Undefined symbols for architecture x86_64:
  "_rt_loadLibrary", referenced from:
  __D4core7runtime7Runtime__T11loadLibraryZQoFxAaZPv in 
drepl.o

ld: symbol(s) not found for architecture x86_64


Re: REPL semantics

2018-07-13 Thread Jacob Carlborg via Digitalmars-d

On Thursday, 12 July 2018 at 22:17:29 UTC, Luís Marques wrote:

Ah, that explains why my clone of drepl didn't compile: it was 
the Martin Novak's repo, not the D community one. Although on 
macOS it still doesn't compile, because of the lack of 
_rt_loadLibrary.


Have you considered using LDC and JIT? [1] [2]. Found this [3] 
snippet as well, not sure what it is.


[1] https://github.com/ldc-developers/ldc/pull/2293
[2] https://github.com/ldc-developers/ldc/releases/tag/v1.8.0 
(mentions something called EasyJIT)

[3] https://gist.github.com/eldar/2294388

--
/Jacob Carlborg


Re: REPL semantics

2018-07-13 Thread Jacob Carlborg via Digitalmars-d

On Friday, 13 July 2018 at 02:26:28 UTC, jmh530 wrote:


No Windows support.

For drepl:
"Works on any OS with full shared library support by DMD 
(currently linux, OSX, and FreeBSD)."


For macOS that means using LDC.

--
/Jacob Carlborg


Re: REPL semantics

2018-07-12 Thread jmh530 via Digitalmars-d

On Thursday, 12 July 2018 at 22:17:29 UTC, Luís Marques wrote:


I actually never tried the existing REPLs, what are your issues 
with them?


No Windows support.

For drepl:
"Works on any OS with full shared library support by DMD 
(currently linux, OSX, and FreeBSD)."





Re: REPL semantics

2018-07-12 Thread jmh530 via Digitalmars-d

On Thursday, 12 July 2018 at 22:24:19 UTC, Luís Marques wrote:


Right. Hopefully there aren't too many weird cases once that is 
generalized to other corners of the language. I also never used 
REPLs for major development, only for debugging and minor 
tests, so I don't have experience with that style of 
development where you code everything in the REPL and then save 
the whole state, which makes it harder for me to evaluate how 
important certain REPL features are.


I primarily use REPL's for prototyping. It just makes some things 
much easier. So for instance, I can load up some functions and 
libraries and data and then run a bunch of different statistics 
models without needing to compile everything again. I can also 
plot everything as needed without needed to compile everything 
all over again.


Re: REPL semantics

2018-07-12 Thread Luís Marques via Digitalmars-d

On Thursday, 12 July 2018 at 19:07:15 UTC, Luís Marques wrote:

Consider a D REPL session like this:


Unlike cling, drepl doesn't seem to support overloading:

Welcome to D REPL.
D> import std.stdio;
std
D> void bar(long) { writeln("long"); }
bar
D> void bar(int) { writeln("int"); }
bar
D> bar(42)
`_mod2.bar` at /tmp/drepl.adse9Q/_mod2.d(3) conflicts with 
`_mod1.bar` at /tmp/drepl.adse9Q/_mod1.d(3)
template `std.stdio.write` cannot deduce function from argument 
types `!()(void)`, candidates are:
/usr/include/dmd/phobos/std/stdio.d(3669):
`std.stdio.write(T...)(T args) if (!is(T[0] : File))`


It can envision the implementation that produces that result, and 
in terms of that implementation it makes sense, but ouch, that's 
not user friendly or in-line with regular D semantics.


Re: REPL semantics

2018-07-12 Thread Luís Marques via Digitalmars-d

On Thursday, 12 July 2018 at 22:04:39 UTC, jmh530 wrote:
I think the mental model of someone coming from a dynamic 
language would be as if bar is dynamically re-compiled when the 
foo(int x) is entered.


Right. Hopefully there aren't too many weird cases once that is 
generalized to other corners of the language. I also never used 
REPLs for major development, only for debugging and minor tests, 
so I don't have experience with that style of development where 
you code everything in the REPL and then save the whole state, 
which makes it harder for me to evaluate how important certain 
REPL features are.


Re: REPL semantics

2018-07-12 Thread Luís Marques via Digitalmars-d

On Thursday, 12 July 2018 at 21:51:18 UTC, aliak wrote:
Cool, is there on going work to sprucing up the D repl in the 
dlang-community repo or is this a new attempt? Either way if 
something is happening here then awesome!


Ah, that explains why my clone of drepl didn't compile: it was 
the Martin Novak's repo, not the D community one. Although on 
macOS it still doesn't compile, because of the lack of 
_rt_loadLibrary.


Regarding your question: I was investigating this as part of my 
own D-related compiler efforts (DHDL stuff), but it won't 
materialize into a D repl anytime soon. I actually never tried 
the existing REPLs, what are your issues with them?


As for your question, hard to say me thinks. On the one hand, 
being able to do this is nice:


const int i = 3;
const int j = 4;
void complexCalculation() { use i and j }
complexCalculation() // uses 3 and 4
const int j = 5;
complexCalculation // uses the new j

On the other hand being able to redefine the name "j" as some 
other type to use in some other computation without having 
`complexCalculation` get messed up is also nice :)


I hadn't even considered *redefining* symbols, only overloading. 
cling doesn't support redefining. Mmmm...



Which is how the swift repl works:

  1> func f(_ a: Float) { print("f") }
  2> f(3)
f
  3> func f(_ a: Int) { print("i") }
  4> f(3)
i
  5> func foo(_ a: Float) { print("f") }
  6> func bar() { print(foo(3)) }
  7> bar()
f
  8> func foo(_ a: Int) { print("i") }
  9> bar()
f


Yeah, I had tried basically the same Swift example. But my point 
stands: I think that behavior can be explained by ease of 
implementation. Finding an example of the alternative would be 
much more interesting. Lacking that we are going to have to 
actually *think* about the problem ;-)


The examples with the dynamic languages are less relevant.


Re: REPL semantics

2018-07-12 Thread jmh530 via Digitalmars-d

On Thursday, 12 July 2018 at 21:15:46 UTC, Luís Marques wrote:

On Thursday, 12 July 2018 at 20:33:04 UTC, jmh530 wrote:

On Thursday, 12 July 2018 at 19:07:15 UTC, Luís Marques wrote:
Most REPLs I've used are for languages with dynamic typing. 
Perhaps take a look at a C REPL and see what it does?


Well, cling calls the original function:

[cling]$ #import 
[cling]$ void foo(long x) { printf("long\n"); }
[cling]$ void bar() { foo(42); }
[cling]$ void foo(int x) { printf("int\n"); }
[cling]$ bar()
long

...but to me that doesn't mean much. If it was the other way 
around (bar was updated to call foo(int)) I think I could 
safely conclude that it was an intended consequence. But the 
actual behavior can easily be explained by the fact that that's 
the most straightforward implementation (especially for a REPL 
that uses an existing C++ frontend, like clang). I was looking 
for a more fundamental answer: what would the user prefer to 
happen?


I think most people, at least most people who have used REPLs 
before, would think that the above should print int. But this is 
because most REPLs are used with dynamic languages. I don't doubt 
that it makes sense that it is easier to implement such that it 
prints long. You're compiling each line as it comes in, so bar 
compiles to some machine code that can only depend on the 
definition of foo at the time it is compiled.


I think the mental model of someone coming from a dynamic 
language would be as if bar is dynamically re-compiled when the 
foo(int x) is entered.


Re: REPL semantics

2018-07-12 Thread aliak via Digitalmars-d

On Thursday, 12 July 2018 at 21:15:46 UTC, Luís Marques wrote:

On Thursday, 12 July 2018 at 20:33:04 UTC, jmh530 wrote:

On Thursday, 12 July 2018 at 19:07:15 UTC, Luís Marques wrote:
Most REPLs I've used are for languages with dynamic typing. 
Perhaps take a look at a C REPL and see what it does?


Well, cling calls the original function:

[cling]$ #import 
[cling]$ void foo(long x) { printf("long\n"); }
[cling]$ void bar() { foo(42); }
[cling]$ void foo(int x) { printf("int\n"); }
[cling]$ bar()
long

...but to me that doesn't mean much. If it was the other way 
around (bar was updated to call foo(int)) I think I could 
safely conclude that it was an intended consequence. But the 
actual behavior can easily be explained by the fact that that's 
the most straightforward implementation (especially for a REPL 
that uses an existing C++ frontend, like clang). I was looking 
for a more fundamental answer: what would the user prefer to 
happen?


Cool, is there on going work to sprucing up the D repl in the 
dlang-community repo or is this a new attempt? Either way if 
something is happening here then awesome!


As for your question, hard to say me thinks. On the one hand, 
being able to do this is nice:


const int i = 3;
const int j = 4;
void complexCalculation() { use i and j }
complexCalculation() // uses 3 and 4
const int j = 5;
complexCalculation // uses the new j

On the other hand being able to redefine the name "j" as some 
other type to use in some other computation without having 
`complexCalculation` get messed up is also nice :)


Which is how the swift repl works:

  1> func f(_ a: Float) { print("f") }
  2> f(3)
f
  3> func f(_ a: Int) { print("i") }
  4> f(3)
i
  5> func foo(_ a: Float) { print("f") }
  6> func bar() { print(foo(3)) }
  7> bar()
f
  8> func foo(_ a: Int) { print("i") }
  9> bar()
f

For reference, this is from node and ruby but not with overloads 
since there's no function overloading: They use the current state 
of the source it seems.



var i = 3;

undefined

function f() { console.log(i); }

undefined

f()

3
undefined

var i = 4;

undefined

f()

4
undefined

Ruby:

2.4.0 :002 > def f0() 3 end
 => :f0
2.4.0 :003 > f0()
 => 3
2.4.0 :004 > def f1() f0() end
 => :f1
2.4.0 :005 > f1()
 => 3
2.4.0 :006 > def f0() 4 end
 => :f0
2.4.0 :007 > f1()
 => 4
2.4.0 :008 >



Cheers,
- Ali





Re: REPL semantics

2018-07-12 Thread Luís Marques via Digitalmars-d

On Thursday, 12 July 2018 at 20:33:04 UTC, jmh530 wrote:

On Thursday, 12 July 2018 at 19:07:15 UTC, Luís Marques wrote:
Most REPLs I've used are for languages with dynamic typing. 
Perhaps take a look at a C REPL and see what it does?


Well, cling calls the original function:

[cling]$ #import 
[cling]$ void foo(long x) { printf("long\n"); }
[cling]$ void bar() { foo(42); }
[cling]$ void foo(int x) { printf("int\n"); }
[cling]$ bar()
long

...but to me that doesn't mean much. If it was the other way 
around (bar was updated to call foo(int)) I think I could safely 
conclude that it was an intended consequence. But the actual 
behavior can easily be explained by the fact that that's the most 
straightforward implementation (especially for a REPL that uses 
an existing C++ frontend, like clang). I was looking for a more 
fundamental answer: what would the user prefer to happen?


Re: REPL semantics

2018-07-12 Thread jmh530 via Digitalmars-d

On Thursday, 12 July 2018 at 19:07:15 UTC, Luís Marques wrote:

Consider a D REPL session like this:


void bar(long x) { writeln(x); }



void foo() { bar(42); }

42


void bar(int) {}


Assuming implementation complexity is not an issue, what do you 
feel is the more natural semantics for a REPL? Should foo now 
call bar(int), or should it still call bar(long)? (feel free to 
generalize the issue)


I was curious to see what the existing REPLs did, but they seem 
to have bit rotted and no longer compile.


Most REPLs I've used are for languages with dynamic typing. 
Perhaps take a look at a C REPL and see what it does?


Re: REPL semantics

2018-07-12 Thread Luís Marques via Digitalmars-d

On Thursday, 12 July 2018 at 19:07:15 UTC, Luís Marques wrote:
Assuming implementation complexity is not an issue, what do you 
feel is the more natural semantics for a REPL? Should foo now 
call bar(int), or should it still call bar(long)? (feel free to 
generalize the issue)


BTW, this succeeds:

long foo(long x) { return x; }
enum x = foo(42);
mixin("int foo(int x) { return x-1; }");
enum y = foo(7);
static assert(x == 42);
static assert(y == 6);

...but is it guaranteed by the spec? Alternatives: 1) 
implementation-defined ordering (of the mixin and the enums), 
possibly different than the existing frontend; 2) 
non-deterministic ordering, can change from one compiler run to 
another.


REPL semantics

2018-07-12 Thread Luís Marques via Digitalmars-d

Consider a D REPL session like this:


void bar(long x) { writeln(x); }



void foo() { bar(42); }

42


void bar(int) {}


Assuming implementation complexity is not an issue, what do you 
feel is the more natural semantics for a REPL? Should foo now 
call bar(int), or should it still call bar(long)? (feel free to 
generalize the issue)


I was curious to see what the existing REPLs did, but they seem 
to have bit rotted and no longer compile.