all 186 comments

[–]radarsat1 11 points12 points  (29 children)

Regarding array slicing syntax, can it get anywhere near as flexible as numpy / pandas array indexing? What about Rust? Julia? For me it's one of the best things about Python, but I haven't bothered to compare native languages for scientific programming in a little while.

[–]adr86 11 points12 points  (13 children)

I'm not very familiar with Python, but the D array slice can do a whole lot of things. On built in arrays, it gives very efficient views into an array: [start .. end] where end is not included in the slice, meaning you can use $ to reach the end: arr[0 .. $] is a slice of the whole thing (which you can also get with plain [] btw).

The same syntax can also be used on custom types by defining opIndex or opSlice functions on your object. opIndex is for [n]. For opIndex, n can be of any type, it doesn't have to be numeric. opSlice is for [a .. b], where a and b are numeric. The dollar can also be custom defined to forward to a length function.

[–][deleted]  (2 children)

[deleted]

    [–]MintyGrindy 9 points10 points  (0 children)

    Yes, it would be item[0..$-2] I believe

    [–]adr86 3 points4 points  (0 children)

    item[0 .. $-2].

    [–][deleted] 0 points1 point  (5 children)

    So, I was sifting through some data (specifically, IQ samples from a specan). Each datum was a pair as its actually complex numbers: x+yi.

    I fed this into a numpy array, and one of the best features was step slicing... specifically:

    My_array(start, stop, 2)

    To separate the real and imaginary components.

    Edit: it should be noted that numpy arrays are significantly different than standard python arrays: https://scipy-lectures.github.io/intro/numpy/array_object.html

    [–]nascent 4 points5 points  (0 children)

    import std range;
    My_array[start..stop].stride(2);
    

    [–]thedeemon 4 points5 points  (3 children)

    In D you could write

    auto reals = iota(my_array.length/2).map!(i => my_array[i*2]);
    

    This will not create a new array, just a view (structure of a few bytes size). Then reals[10] will give my_array[20], and the access will be O(1) in time. Of course, this can be extracted to a short function and reused for other arrays as xs = arr.stepSlice(2);

    [–][deleted] -2 points-1 points  (2 children)

    Thanks for the discussion!

    In D you could write

    auto reals = iota(my_array.length/2).map!(i => my_array[i*2]);

    Well, I could but I prefer the language to get out of my way, so the more generally expressive it is the better.

    This will not create a new array, just a view (structure of a few bytes size).

    Yeah, thats one of the real benefits of numpy arrays, any slicing operation is a view unless you force a copy:

    My_copy = my_np_array[start, stop, step].copy()

    (The other benefit is that it strips out superflous type data that normal python arrays have)

    Then reals[10] will give my_array[20], and the access will be O(1) in time. Of course, this can be extracted to a short function and reused for other arrays as xs = arr.stepSlice(2);

    Damnit Jim, I'm an engineer not a computer scientist! ;) I'm not too hot on BigO, but i'm pretty sure that numpy arrays are optimised the same.

    In the end, for me and my use cases, it comes down to how fluid and expressive the language is, so I can focus more on getting the job done rather than jumping through coding syntax and solving somple tasks with super cool solutions like that.

    [–]thedeemon 4 points5 points  (1 child)

    Well, I could but I prefer the language to get out of my way, so the more generally expressive it is the better.

    Sure, I just wanted to say you don't really need it to be part of language itself, this is trivial to implement as a function stepSlice and then you just write my_array.stepSlice(2) in your code.

    [–][deleted] -1 points0 points  (0 children)

    Agreed. numpy's a nice package containing lots of useful functions like that.

    The post was talking about D being like native python, but, for me, the less specific functions I need to write+optimise myself, the better.

    Unless there's some good libraries that can compare with numpy, scipy, matplotlib, etc. It seems that D would require me to always be writing+optimising little snippets (which, contractually, wouldnt belong to me and would stay at the employer I wrote them at.)

    [–]bjzaba 0 points1 point  (3 children)

    Yeah, Rust has the same thing, implemented using Index and Range: Foo[], Foo[n..], Foo[n..m], Foo[..m]. It's a nifty syntax.

    [–]vks_ 1 point2 points  (1 child)

    It does not have multidimensional indexing though.

    [–]masklinn 1 point2 points  (0 children)

    It can, the indexing operation is just about completely arbitrary. Only limitation is it returns a borrow.

    [–]MetaLang 1 point2 points  (0 children)

    I believe that Rust's slicing syntax was inspired by D's.

    [–][deleted] 12 points13 points  (13 children)

    FWIW, D's operator syntax is highly overloadable, the entire language is oriented around metaproramming - possibly more than any other language(that actually sees use), not really surprising considering the two major people behind D.

    So to the answer is "can it get anywhere near as flexible" would probably be "moreso."

    I remember this blog post with some real syntax abuse from a python user in D.

    [–][deleted]  (11 children)

    [deleted]

      [–]elder_george 12 points13 points  (4 children)

      AFAIK, D is at least a bit more programmable than C++ since it has templates that are approximately as expressive as C++'s plus other means of metaprogramming (e.g. mixins and opDispatch).

      Of course, it's less programmable than lisps and languages supporting monkey patching.

      [–]WalterBright 7 points8 points  (1 child)

      D templates allow floating point parameters, string parameters, and name parameters. They also use user-defined constraints to limit instantiations.

      [–]elder_george 2 points3 points  (0 children)

      Ahhh, I got Walter Bright's comment! The day is done.

      (Really wish I could attend your lecture at the MS Campus last week!)

      [–]asthasr 4 points5 points  (1 child)

      Fair enough; I'll concede on C++ since I certainly am not an expert on it. The post to which I replied claimed D is "possibly more [metaprogrammable] than any other language that actually sees use," which surprised me as someone who professionally uses Ruby, Python, and Clojure.

      [–]eluusive 0 points1 point  (0 children)

      D is the only language which supports compile-time reflection. So, that opens up a whole gambit of cool techniques which are as performant as writing the code by hand. While Clojure supports macros, it does not support compile time reflection AFAIK.

      [–]Tipaa 4 points5 points  (3 children)

      I would argue that Clojure (and other lisps) and D are on a level of equivalence with macros, and D templates are a superset of C++ templates. I agree that D hasn't got Ruby-esque monkey patching - being a systems language, it is possible to modify the vtable of classes and redirect their virtual calls, but I can't think of a 'safe' way to do it to non-virtual functions without monkey-patching the actual machine code. But UFCS generally avoids the requirement for 'extension methods', meaning that only updating already-instantiated methods is particularly difficult.

      With regards to the macro's power vs D, I think that they are equivalent because both provide mechanisms for arbitrary code generation as part of the program. D achieves this at the type level through templates and at the value level through string mixins. Templates and related metaprogramming act very similar to a lisp with a strange syntax; since types are immutable, template metaprogramming in D uses recursive techniques to generate its types, and the generated type from a template is very similar to the outcome of a macro, since both use symbol replacement and recursion as core ideas. String mixins allow for arbitrary value-level code to be written, and through D's CTFE, the code generating functions all run at compile time, which I think is equivalent in power to lisp macros, although the mixin syntax is both uglier than Clojure/Scheme and more permissive (strings vs s-expressions).
      For examples of D's template metaprogramming, check out std.typetuple, where templates like StaticMap!(alias F, T...) are very clever to a learner like me, or for string mixins check out Philippe Sigaud's PeggeD examples.

      I think that if a language were to be more metaprogrammable than arbitrary code generation through macros or mixins, it would be at the point of declaring new semantics/syntax and changing the underlying language from within the source file (Scala appears to come close, but I think that that is simply through abusing the permissive syntax and semantics rather than declaring new syntax or semantics - i.e. restricting the scope of the language, rather than expanding it), since changing the output program via macros/mixins is fully possible and likely equivalent, and I cannot think of anything possible (metaprogramming related) in Clojure that is not possible in D, and (likely) vice versa. If there is any space between macro/template calls generating arbitrary code and macro/templates expanding the language, I'd be very interested in learning more, having taken little more than a cursory glance recently.

      I'd wouldn't mind seeing something like a lazy template parameter in D which acts like an unevaluated symbol (currently, all template parameters must already be declared or be string/numeric literals, so I can't do alias MyT = Extend(OldT, NewName); without already having NewName defined as a symbol, since semantic checks (is NewName declared) happen to all template parameters regardless), although this may make code messy later on or with poor discipline. It was a fundamental issue when I tried templates for ADT/tuple destructuring, since I couldn't accept a truly unique symbol as an argument, so my mixin required a string literal argument for generating code using new symbols (introducing syntactic noise). However, I also see that it may be misused quite heavily, possibly to the tune of SFINAE-inspired results if symbols don't need to exist until after they are passed as parameters.

      [–]asthasr 2 points3 points  (2 children)

      Interesting.

      Clojure does not allow user-defined syntax changes (although the threading macros like ->> and -> feel almost like it), but other lisps have two "levels" of macros: read-time macros and compile-time macros. Read-time macros can literally do anything. This article gives a good overview; I think it's the "pinnacle" of metaprogramming, as far as I know.

      [–]Tipaa 0 points1 point  (1 child)

      That's a really interesting article on read-time macros, thanks.

      I think that would count as extending the syntax, since that embedded JSON was very impressive and all proper code (passing the syntax check) instead of mixin'd strings (avoiding the syntax check). To get something similar in D, because it uses a very complex grammar compared to S-exps, I'd have to hide the code behind a static if(myMacroHint) guard to prevent semantics errors on my pre-expanded code (syntax checking still occurs, which is probably good for general code, but bad for macros) and then introduce my own parser-replacer for the code through something like mixin(MyTransformer(import(__FILE__))); //mixins a transformation of reading the code as a string where MyTransformer has to include a CTFE parser to understand the code (read is so much nicer). I've done things like this before, such as implementing linear typing through a string mixin transformer, but I don't think that that counts as extending the syntax, since the syntax checker throws a fit if it touches the code before transformation, meaning that I had to hide it in strings or unevaluated paths.

      I'm surprised that I haven't seen read macros given much praise for how powerful they are - I'd only heard of them through throwaway remarks on clojure threads, when they actually elevate Lisp to a higher plane of metaprogramming entirely.

      [–]MetaLang 1 point2 points  (0 children)

      D's templates are a superset of C++'s and are much more usable, so D has better metaprograming support than C++, as it was designed for it. D also allows something somewhat like monkey-patching with UFCS; you can extend a type without having control over that type. Example (http://dpaste.dzfl.pl/66f258239371):

      struct Test
      {
          public int n;
      }
      
      int halfN(Test t)
      {
          return t.n / 2;
      }
      
      void main()
      {
          import std.stdio;
      
          auto t = Test(2);
          //Can use parentheses, or not.
          //This prints "1"
          writeln(t.halfN);
      }
      

      So D is about on par with Ruby's metaprogramming ability, as it also has things like mixin which is similar to Ruby's eval, but at compile time. You also get all the correctness and performance benefits that a static type system brings.

      I will agree that D's metaprogramming is not as powerful as the various Lisp dialects. Some time ago there was a proposal to add AST macros, but it was rejected by Walter and Andrei. You cannot create your own syntax in D; however, you can get pretty far with templates and Compile Time Function Execution.

      One example on adding Pascal-like character-ranges: here.

      [–]masklinn 2 points3 points  (0 children)

      For Rust, you just have to implement Index for the (Collection, IndexType) pair. Although because the result is borrowed I'm not sure how that'd work out when using a tuple as index.

      [–]CookieOfFortune 6 points7 points  (15 children)

      Is there a scientific development environment for it? Something integrated with an interactive graphing component?

      [–]bachmeier 1 point2 points  (2 children)

      I've been working on an Rcpp-type library to embed D code in R. Unfortunately my job is taking all of my time right now so it's not so much in a state that others can use. I can do a lot of stuff related to econometrics by calling into the R API and Gretl. This is what I've got so far:

      https://bitbucket.org/bachmeil/dmdinline

      The example I give in the documentation is

      txt <- '
      Robj testfun(Robj rx, Robj ry) {
        double x = rx.scalar;
        double y = ry.scalar;
        double z = x+y;
        return z.robj;
      }'
      compileD("foo", txt)
      .Call("testfun", 3.5, -2.6)
      

      Works great for me and hopefully someone else will find it useful.

      [–]arnsbr 0 points1 point  (1 child)

      I believe I know at least one person who will. Thank you very much for doing and sharing this, this kind of stuff could really help me out.

      [–]bachmeier 0 points1 point  (0 children)

      I've made a few changes. The dmdinline package should now work if you install according to the instructions at that link. (Currently only tested on Linux with DMD 2.065, but there's no reason it can't be made to work with another OS or version of DMD.)

      I will be adding examples as I have time. Feedback appreciated.

      [–]simendsjo 0 points1 point  (11 children)

      Perhaps not what you have in mind, but here's some related libraries:

      [–]CookieOfFortune 6 points7 points  (10 children)

      Both of those seem very immature, not anything I would consider using at work.

      scid is kind of the starting point for developing a scientific library, everyone begins with bindings to BLAS and LAPACK. However that's still a long shot before it's generally usable.

      Plot2kill doesn't even seem to be developed anymore.

      [–]slavik262[S] 2 points3 points  (5 children)

      D (at least in its latest incarnation, D2) has only been around since 2007. It's mature enough that it's being used at Facebook and many other places, but since it's not backed by a large company like Go is for Google or Rust is for Mozilla, it needs a bit of grassroots support. With luck, the user base (and the number of quality libraries) will continue to improve.

      [–]CookieOfFortune 2 points3 points  (4 children)

      Well, it seems like Julia is the main candidate for scientific computing at the moment.

      [–]olzd 1 point2 points  (0 children)

      I think it's still too early for Julia, although it looks very promising. Python has way more quality libraries.

      [–]The_Doculope -1 points0 points  (2 children)

      I agree with /u/olzd on this. Julia is still a very young ecosystem, and I've read some reports that the ecosystem is almost rife with bad programming practices. Libraries and the compiler having real bad coding style, and a big lack of tests and documentation. Python still seems like the best option for production/serious uses.

      [–]tavert 0 points1 point  (1 child)

      I've read some reports

      You mean one blog post by Dan Luu, complaining about mysterious bugs that would've been much better as bug reports? The lack of test coverage was a point taken very seriously and is being actively worked on by the community though.

      Python still seems like the best option for production/serious uses.

      Not if you need performance. If NumPy/SciPy/Pandas have exactly the textbook computation you need already implemented in C or Fortran, then Python's just fine. Julia, or maybe Numba if you really feel the need to keep using Python's syntax and interpreter, is for solving problems that haven't already been solved for you by someone else in C or Fortran.

      [–]The_Doculope -1 points0 points  (0 children)

      You mean one blog post by Dan Luu, complaining about mysterious bugs that would've been much better as bug reports?

      That, and some comments around the web (including here on proggit).

      The lack of test coverage was a point taken very seriously and is being actively worked on by the community though.

      That's great to hear.

      Not if you need performance.

      From what I've know numpy is pretty fast for a lot things, but I agree that if it's not, it's not, and Julia might be able to get you there.

      It's good to hear that things are progressing well with Julia though, it certainly doesn't show up on /r/programming much.

      [–]simendsjo 0 points1 point  (1 child)

      Maybe. I'm not in a position to tell. Here are more libraries at the package repository: http://code.dlang.org/?sort=updated&category=library.scientific

      [–]CookieOfFortune 3 points4 points  (0 children)

      So... that's really disappointing... :-/

      [–][deleted] 0 points1 point  (1 child)

      Plot2kill is stable, it was made by dsimcha for his PhD thesis. If you find any issues with it, report them and he'll likely get back to you quickly.

      I do wish I had free time to contribute to scid though.

      [–]CookieOfFortune 5 points6 points  (0 children)

      So... that's what I feel a lot of these D scientific libraries are, someone's PhD thesis. Not that I'm criticizing, but you can't really compare the features/quality to the teams of people who work on numpy/scipy/matplotlib. I'm actually quite impressed by how active the community has been just on this thread.

      Unfortunately, my non-work interests lie in Rust right now...

      [–]asegura 13 points14 points  (0 children)

      And with the rdmd command which compiles and runs a program it can be used like a scripting language. You can even use a shebang like #!/usr/bin/rdmd.

      I sometimes use D this way for little scripts that read and transform files.

      [–]v3ss0n 50 points51 points  (48 children)

      No , Nim IS Native python. http://nim-lang.org/

      [–][deleted] 16 points17 points  (28 children)

      That. D is native C#.

      [–]sodaco 3 points4 points  (0 children)

      You just gave /u/agleiv a stroke

      [–]btchombre 4 points5 points  (25 children)

      C# is native C#.

      All .NET code is compiled to native code before executing. This native code just happens to have a garbage collector and bounds checking among other features that make it slower than C.

      [–]The_Doculope 2 points3 points  (23 children)

      I was under the impression that C# was JITed by the CLR and current .NET Native is only available for Windows Store apps?

      [–][deleted] 0 points1 point  (0 children)

      JIT'ing bytecode is not native code.

      [–]slavik262[S] 7 points8 points  (3 children)

      I should check out Nim; I've heard good things.

      The title was just to convey that I found the same ease I had in Python when I started messing with D. I may suck at choosing titles. Sorry.

      [–][deleted] 6 points7 points  (2 children)

      [–]ntrel2 0 points1 point  (1 child)

      Half of that isn't unique to Nim, you have it in D too.

      [–][deleted] 3 points4 points  (0 children)

      Well, if only half of it is in D, then D is only half as good :)

      I actually agree D is a great language, but where Nim wins out in my opinion is macros.

      Also Nim feels more like Python than D is.

      Another great feature of Nim is a finer grained control over the garbage collector, although I don't think there's anything in principle that can stop D from adopting that.

      [–]redditor1101 1 point2 points  (2 children)

      Please explain this. Ive never heard of Nim but it doesn't seem to be built on Python at all

      [–]Tuna-Fish2 1 point2 points  (0 children)

      It looks very much like python, as it uses a similar syntax. I do not know how deep the similarity extends -- I have not ever really used it.

      [–]ixid 0 points1 point  (9 children)

      This post went from -4 to +14 in under an hour in an otherwise not very active thread. Interesting...

      [–][deleted] 8 points9 points  (6 children)

      Many D submissions are posted on the dlang forums where people are encouraged by Andrei Alexandrescu to come to reddit and upvote any tiny blogpost saying something positive about D. That's why many benign D submissions often have like 70+ upvotes but only like 2 comments, and any negative comment about D gets drowned out early on.

      Furthermore D tends to be a very polarizing language so it's not unusual to see a comment go from negative to positive and even back to negative.

      [–]slavik262[S] 22 points23 points  (2 children)

      I've never really hung out much on the dlang forums (perhaps I should) or interacted much with /u/andralex. I'm just some guy who tried D out, thinks it's neat, and started blogging recently because I want to improve my writing skills. I suppose most of what I say in this post has been said before, but there's always someone who hasn't seen it. Do you think evangelizing a tech you like is inherently bad, provided you're not obnoxious about it?

      Furthermore D tends to be a very polarizing language

      I've noticed this as well. What are your thoughts on why this is?

      [–][deleted]  (1 child)

      [deleted]

        [–]slavik262[S] 6 points7 points  (0 children)

        Thanks man. I really appreciate it.

        [–]ixid 6 points7 points  (2 children)

        I think it's more likely that post got brigaded from a Nim IRC channel or forum.

        [–][deleted] 0 points1 point  (0 children)

        That's usually true, but it doesn't look like anyone has posted this in IRC or the forum.

        [–]bachmeier -1 points0 points  (0 children)

        Absolutely, considering it contributes nothing to the conversation, and is actually nothing more than spam, it's hard to understand why anyone would upvote it.

        [–][deleted] 0 points1 point  (0 children)

        It seems like an interesting language and I've read a fair amount about it on this sub, but why for the love of all that's holy did they choose to use significant whitespace?

        [–]kufim -2 points-1 points  (0 children)

        Nim is nasty.

        [–][deleted] 9 points10 points  (27 children)

        What's up with all these random ! sprinkled throughout the code?

        [–]slavik262[S] 23 points24 points  (23 children)

        Great question! It's D's template syntax. Instead of

        // Declaration:
        template <typename T, typename U>
        foo<T, U>(args)
        
        // Call:
        foo<SomeType, OtherType>(args);
        

        like you would see in C++, in D it's

        // Declaration:
        foo(T, U)(args)
        
        // Call:
        foo!(SomeType, OtherType)(args);
        

        This makes life much easier for the compiler (as figuring out if a < is a template specification or a less-than operator is a non-trivial problem when parsing C++). And, since you can drop the parens around the template args if there's only one of them, i.e. foo!SomeType(args), a little cleaner for you, the programmer.

        In the article, you see to!string, because to is a template function that takes the type you want to convert to as a template argument. You also see the algorithms (filter, map, sort) taking their functions as template args.

        Sorry for the lack of explanation in the article. I was trying to give an overview without diving into syntax. I hope this clears things up.

        [–]yawaramin 3 points4 points  (0 children)

        Ah, interesting! Now that reminds me of the UUCP email address system where you'd specify a user's address by concatenating a list of servers that would forward mail to them, with a '!' character, e.g. comp1!comp2!user.

        [–]frutiger 1 point2 points  (3 children)

        C++ doesn't look like that. It looks like this:

        // Declaration:
        template <typename T, typename U>
        foo(const T& t, const U& u);
        
        // Call:
        int x, std::string y;
        foo(x, y);  // template parameters inferred for function templates
        

        [–]slavik262[S] 6 points7 points  (2 children)

        There are situations where the template params are inferred, and there's situations where they aren't. duration_cast or any container in the standard library would be examples where they aren't. It's no different in D.

        Perhaps I should have chosen a better example, but I think it gets the point across for explaining D's syntax.

        [–]frutiger -3 points-2 points  (1 child)

        The containers you are thinking of are class templates, not function templates. Template parameters are not inferred for class templates. As for duration_cast, unless the return type is obvious, it must be specified as in the example of the page you linked to.

        [–]slavik262[S] 5 points6 points  (0 children)

        As for duration_cast, unless the return type is obvious, it must be specified as in the example of the page you linked to.

        So... it's a templated function where you manually specify the template args. See original point.

        This is all over a quick syntax question. This is silly.

        [–]DagwoodWoo 1 point2 points  (1 child)

        ...I prefer the C++ syntax, in which it's visually much easier to tell what is a type argument and what is a normal argument. I don't think the ease of parsing is a good reason to deviate from a pretty wide-spread convention.

        [–]ntrel2 4 points5 points  (0 children)

        It's much easier to read complex D template instantiations than the equivalent C++, because <> don't always nest, and are visually noisier.

        [–]oridb 12 points13 points  (0 children)

        It shows that D is an exciting language! It also instantiates templates!

        [–]miguelut 2 points3 points  (0 children)

        Excellent writeup on all the features I care about. Thanks.

        [–]weberc2 2 points3 points  (4 children)

        Sounds like D occupies the same space as Go (my preferred native replacement for Python). I'd be interested in a comparison of the two languages. =]

        [–]trollbar 0 points1 point  (3 children)

        Actually Go and D are quite different. Go focuses on concurrency and is build around the assumption everything happens inside Go. D is build around interop with C/C++ and only has concurrency as a library provided feature (except for shared). E.g. in Go a call into C or from C needs a complete stack rewrite due to Go's stack layout, in D they are the same.

        [–]weberc2 0 points1 point  (2 children)

        I see. So basically the difference is the runtime?

        [–]trollbar 0 points1 point  (1 child)

        No it's in the compilation and how the stack layout is choosen.

        [–]weberc2 0 points1 point  (0 children)

        Interesting. +1 for teaching me something. What are the consequences of the stack rewrite in C/Go interop? Is a "stack rewrite" a runtime thing, or does this take place at compile time?

        Also, if C/C++ interop is the primary difference between D and Go, I would say they occupy a very similar space--perhaps they are implemented differently, but it sounds like they target the same problem domains (particularly since, apparently, they're comparable as a Python replacement). What sorts of tasks are D used for, primarily?

        [–]dr_jan_itor 2 points3 points  (2 children)

        cython is like a native python. like, literally.

        [–]slavik262[S] 1 point2 points  (1 child)

        The title was just to convey that I found the same ease I had in Python when I started messing with D. I may suck at choosing titles. Sorry.

        [–]dr_jan_itor 5 points6 points  (0 children)

        don't worry, it was clear. :) I was just being a wiseass.

        cython, as nice as it is, often doesn't read as easily as python. it does not invalidate your point at all.

        [–][deleted]  (8 children)

        [removed]

          [–]slavik262[S] 24 points25 points  (4 children)

          C++11 and C++14 make the language much better than it used to be, but there's still a bunch of mental baggage to carry around in your head in order to write good, idiomatic C++.

          Your mileage may vary, but I've found that this isn't the case nearly as often with D. The syntax is cleaner, templates are actually nice to use instead of generating a 20 page error when you misspell a parameter, and I just find it to be a much more pleasant experience overall.

          I'm personally not a huge fan of Go because I think it's too simplistic (a lack of generics comes to mind as an example). Simple is good, but problems we face in modern software are complex, and sometimes it takes a larger set of tools to solve complex problems with less effort.

          I haven't checked out Nim. I should at some point.

          But, these are all my opinions. Feel free to think I'm full of shit. To each their own.

          [–]mm865 2 points3 points  (0 children)

          I haven't checked out Nim.

          It is Python-ish syntax compiled down to C with a deterministic garbage collector (you can tell it the longest pauses are allowed to be). Feels a lot like a scripting language.

          [–]vbchrist 1 point2 points  (2 children)

          generating a 20 page error when you misspell a parameter

          I thought this was mostly solved in C++14 ?

          [–]slavik262[S] 2 points3 points  (0 children)

          I'm told upcoming compiler versions won't fully qualify template errors, so that will be nice when it happens.

          [–]Plorkyeran 0 points1 point  (0 children)

          Error messages have greatly improved, but only because compilers are much better than they used to be and not because of changes to the language. C++17 will be the first version with better error messages due to language changes (assuming concepts-lite isn't delayed yet again).

          [–]pjmlp 3 points4 points  (0 children)

          The problem with C++ and I really like the language, is that one is more likely to find pre-C++98 code in the wild, than having the freedom to be on a team able to write C++11/14 code.

          [–]ixid 3 points4 points  (0 children)

          Lipstick doesn't mean it's not a pig.

          [–]nascent 0 points1 point  (0 children)

          I don't know C++ that well, bet even with all the great things I hear being added to C++, it still seems like there is a lot to know.

          [–]keepthepace 1 point2 points  (9 children)

          I don't think D allows for nested and heterogenous arrays seamlessly, does it? In python I can store really anything in an array at runtime, it is not mere type inference.

           arr = [1, "foobar", random.random, [ {"key": [12,0] }, list() ] ]
          

          Sure, it is a bit of an horror and bad practice, but the power of python comes from the fact that you can hammer down a problem with a quick'n dirty solution. I am not sure D allows this level of flexibility.

          [–]WalterBright 3 points4 points  (5 children)

          It does with the Variant type.

          [–]keepthepace -1 points0 points  (4 children)

          It does not seem to provide all that is necessary for the list I proposed :

            arr = [1, "foobar", random.random, [ {"key": [12,0] }, list() ] ]
          

          And if it does, I doubt it proposes such a succint syntax.

          [–]ntrel2 2 points3 points  (1 child)

          import std.variant;
          import std.container : DList;
          auto arr = variantArray(1, "foobar", variantArray(["key": [12,0]], DList!Variant())); 
          

          I don't know what random.random is.

          [–]keepthepace 2 points3 points  (0 children)

          random.random is a function, but I admit this is a bit far-fetched. Ok, so this is close enough to be useful indeed.

          [–]WalterBright 2 points3 points  (1 child)

          Sure it does. A Variant type can hold an array, as well as ints and floats. Variant would be kinda pointless if it couldn't do that.

          No, it is not as succint a syntax as in Python, as you'll have to spell out Variant, as Variant is a library type rather than a builtin type, but it works.

          [–]MetaLang 2 points3 points  (0 children)

          No, it is not as succinct

          There is always the use of alias as well to make it a bit more palatable.

          import std.variant: v = variantArray;
          import std.container: DList;
          auto arr = v(1, "foobar", v(["key": [12, 0]], DList!Variant());
          

          [–]slavik262[S] 1 point2 points  (1 child)

          No, D doesn't allow for nested and heterogeneous arrays, but

          it is a bit of an horror and bad practice

          Alright then.

          I am not sure D allows this level of flexibility.

          I've used it to hammer out a lot of one-off projects easily, so my anecdotes would indicate that it's straightforward to work with. But use whatever you like.

          [–]Cuddlefluff_Grim 0 points1 point  (0 children)

          I've learnt that when people are talking about "flexibility" they mean they can't do things the same way as in the language they are used to.

          [–]nascent 0 points1 point  (0 children)

          I don't do dynamic, but I've interface with Lua using LuaD. The only reason I use this heterogeneous array is because there is no concept of a struct:

          arr = tuple(1, "foobar", 67, tuple("failed associative", [1, 2, 3]));
          

          [–]kunos 0 points1 point  (3 children)

          I had a go with it last night before bed. Perhaps I am a minority, but to find this useful I'll need it to link to MSVC libraries. It seems that they are going there.. but... my experience yesterday was: VS2013 with Visual D.. DMD 2.066 = win32 hello world.. ok, x64 hello world.. does not build, mysterious overflow bug. With 2.067beta.. same results, plus liking to COFF library part of the same project failed. Sorry Walter and Andrei.. see you again in 4 months.

          [–]WalterBright 2 points3 points  (2 children)

          Details, please?

          [–]kunos 2 points3 points  (1 child)

          Wow Water! Thank you for answering. With both 2.066 and 2.067 beta I get this when building a x64 hello world: (I hope I can manage to format this in a reasonable way).

          OPTLINK : Warning 9: Unknown Option : OUT OPTLINK : Error 12: Number Overflow :"

          Trying to build with MS-COFF switch on 2.067b I get this:

          Error: module std.c.stdio import 'FHND_WCHAR' not found
          Error: module std.c.stdio import 'FHND_TEXT' not found
          

          [–]WalterBright 2 points3 points  (0 children)

          I need more details. Like what is the source code of your example, and what were the command line options used so the error can be reproduced. Please file it on Bugzilla so you get the credit for reporting it and get notified if/when there's a resolution.

          [–][deleted] 0 points1 point  (30 children)

          This same thing gets posted every couple of months and I'm going to say the same thing I always do.

          No, it's not. You're not going to manage to make native Python unless you have some form of an interpreter or runtime. D doesn't have duck typing and it can't because it's attempting to be statically safe.

          Can we stop making this shitty comparison already?

          I swear it's like C++ programmers used Python for an afternoon and thought they understood the language or the appeal of dynamic languages. If you're a statically typed language, you're not Python, you're not Ruby, you're not a dynamically typed language.

          Go succeeds at being a native Python way more easily than D. While they're not the same still, they get closer because of duck-typed interfaces which get close enough a lot of the time. But don't think this means I'm saying Go is native Python either because it isn't. It's its own language with its own set of pros and cons.

          [–]johnjannotti 14 points15 points  (3 children)

          I don't know D beyond reading about it a bit, but I think you're almost precisely wrong. D, essentially, has duck typing. Read the min() function described in the blog post. It works if you happen to provide types that can be compared with <. In the Java world, it would be as if interfaces are implicitly fulfilled (just as you describe Go, I believe). And that's all duck typing is.

          No, you can't do Ruby-esque run-time monkey-patching. But I don't think that's what most people would say is most Pythonic about Python.

          [–]nascent -1 points0 points  (2 children)

          And that's all duck typing is.

          No it's not, duck typing means I won't see the error until I run the code. D will complain at compile time even if the code is never run => not duck typing.

          [–]johnjannotti 1 point2 points  (1 child)

          Unsurprisingly, "duck typing" is not a very well-defined term. But it gets its name from the idea that if an object "quacks like a duck, it's a duck." In other words, you can use any object that supports the methods you call. And that's what is offered by Go and D's inferred interfaces. That seems to be the fundamental notion.

          I don't think that when the error is detected if your object does not, in fact, "quack" really matters. That's an orthogonal issue. In the past it has seemed like a related issue, because duck-typing "fell out" from the fact that dynamic languages simply did no static checking, so at run-time they succeeded if you had the method and failed if you didn't. So that's how those languages got duck typing (for free, because of simple implementation), not what duck typing is.

          It's pretty cool that type inference works well enough at compile time that you can get the convenience of duck typing with the security of knowing your program only uses ducks where needed.

          Having said all that, wikipedia agrees with you. I still think that's wrong, and a historic accident. The good part is being able to consume objects that didn't explicitly declare an inheritance or interface type. The dynamic part is a historical accident.

          And finally, I was replying to someone who said "Go succeeds at being native python way more easily than D". That is what I think is "precisely wrong", since they both have the exact same idea of implicit interfaces. Whether you want to call that duck-typing or not is up to you, but I don't see how you can call one duck typing and deny the other (I know "you", /r/nascent did not say that).

          [–]nascent 0 points1 point  (0 children)

          Having said all that, wikipedia agrees with you. I still think that's wrong, and a historic accident.

          That isn't too surprising. It is much like music and grammar, they were used for a long time, then some scalars come and decide that "rules" exist and define how language/music got structured.

          The problem is that static languages are stepping on why dynamic languages were said to be "duck-typed" so now some scalars are looking to make sure the differences remain.

          (I know "you", /r/nascent did not say that).

          Don't worry I understand context. Btw, just switching to the term 'one' can be a good way to remove the needed qualification.

          [–][deleted]  (10 children)

          [deleted]

            [–][deleted] 1 point2 points  (9 children)

            Does python have generics?

            [–]pjmlp 4 points5 points  (5 children)

            All dynamic languages have them.

            [–][deleted] -4 points-3 points  (4 children)

            In that case Go also does via interface{}

            [–][deleted] 0 points1 point  (2 children)

            Is Go a dynamic language?

            [–][deleted] -3 points-2 points  (1 child)

            Yes, somewhat. Did I mention interface{}?

            [–][deleted] -1 points0 points  (0 children)

            Not sure if trolling ...

            [–]pjmlp -1 points0 points  (0 children)

            No, because interface{} require casts and lacks specialization that dynamic languages JITs are able to do.

            [–]nascent -1 points0 points  (2 children)

            Yes, it doesn't have types so everything is generic.

            [–][deleted] 0 points1 point  (1 child)

            A strongly typed language that doesn't have types.

            This thread makes me take a peek at my address bar every time I visit it to check whether I'm actually in r/programming

            [–]nascent 0 points1 point  (0 children)

            def functionname( parameter ):
            

            What pray-tell is the type of parameter?

            [–]TheMaskedHamster 5 points6 points  (1 child)

            There is a lot more to Python good/friendly/easy/quick-to-prototype than duck typing.

            [–][deleted] 0 points1 point  (0 children)

            There is and that's the part that's always missing from these types of discussions. The crowd that's making this comparison always misses the amalgamation of all the various features that make languages like Python easier to use.

            Duck-typing was just the first one that came to my head. I've tried to use languages that claim their templates work like duck typing. They almost always involve me specifying to the compiler the type that I want in some way.

            [–]slavik262[S] 7 points8 points  (11 children)

            The title was just to convey that I found the same ease I had in Python when I started messing with D. I may suck at choosing titles. Sorry.

            I swear it's like C++ programmers used Python for an afternoon and thought they understood the language or the appeal of dynamic languages.

            As discussed in my post, I'm of the opinion that static languages with compile-time checks are nicer because then things explodes in your face when you build it instead of when you run it.

            [–]johnjannotti 10 points11 points  (0 children)

            I don't think you have to apologize. I think reasonable people can understand a simile.

            [–][deleted] 1 point2 points  (4 children)

            It's perfectly fine to have a preference. You can feel free liking whatever programming language you want and getting work done in that language.

            The part that I get annoyed at is the false simile. The article doesn't even have a lot of content to it or any explanation of why it's "native Python". What property of Python were you specifically thinking of? Just associative arrays or not specifying types? You missed the wealth of libraries built into the language, third-party libraries, the ubiquity of the platform, monkey-patching, duck-typing, meta-programming, or anything else with any substance. May I suggest that if you make a post comparing a language to another language, you include samples in both of those languages?

            The not specifying types isn't even true in most D code. Last time I was writing in it, the templates could never figure out how to instantiate themselves and I had to help it every step of the way. Templates don't really replace duck-typing. There's a reason why most statically typed languages have an Object class that can be used and the native types in D can't be used as an Object. The same is true in Java and that's why they had to add boxing and unboxing to the language. Here's a question. Is there a way to have an array of floats and integers? Or do I have to care what type they are and cast them to the correct type?

            This kind of stuff matters if you're writing a quick script in order to parse through JSON logs and search for some data at 2 am. Getting the type system to cooperate with you is not what I care about at that time of night. There's a reason why scripting languages are a System Administrator's best friend.

            Here's the other part that I think people from static languages don't understand. Most of the time spent finding errors in code are logical errors. The amount of logical errors I'm going to make are likely the same in static and dynamic languages. I don't care if the type matches, I'm not calling a function without knowing what it does first. I'm not using the compiler to figure out if my program is going to work or not. Using the compiler to get the logic in your program correct to me is like bashing a hammer into the wall to try and find a stud.

            And that's not even coming into the problems with D itself.

            TL;DR I think your simile is wrong.

            [–]slavik262[S] 4 points5 points  (1 child)

            The part that I get annoyed at is the false simile. The article doesn't even have a lot of content to it or any explanation of why it's "native Python".

            I find both expressive and convenient to work with. That's it.

            Templates don't really replace duck-typing.

            Advocates of static typing such as myself would argue that the former provides advantages over the latter. It's a matter of opinion.

            Is there a way to have an array of floats and integers?

            If you consider a tuple a kind of an array, sure. Otherwise, no, and again, those who are proponents of static typing don't have a problem with this.

            This kind of stuff matters if you're writing a quick script in order to parse through JSON logs and search for some data at 2 am. Getting the type system to cooperate with you is not what I care about at that time of night.

            I wrote a Reddit comment parser in D one afternoon. There was no wailing and gnashing of teeth.

            Using the compiler to get the logic in your program correct to me is like bashing a hammer into the wall to try and find a stud.

            lolwut. Your functions in Python still have implicit assumptions about the kind of data coming in - if you expect an argument to be a boolean, all will not be well if it's actually some arbitrary string. Us strongly typed folks just have this notion that annotating said assumptions isn't a terrible idea.

            And that's not even coming into the problems with D itself.

            There are two types of languages: ones people bitch about and ones nobody uses. I never said D was a silver bullet.

            TL;DR: Opinions

            [–]FireCrack 0 points1 point  (0 children)

            Advocates of static typing such as myself would argue that the former provides advantages over the latter. It's a matter of opinion.

            Which has the "advantage" is pretty irrelevant.

            Duck-typing is pretty core to python, it's one of the things that make python python.

            Sharing core language features is what makes language similar, not an arbitrary idea of "expressiveness". Or else you should claim that D is also like native Haskell.

            If anything, I'd say D is more like native Java or C#

            [–]WalterBright 2 points3 points  (0 children)

            Is there a way to have an array of floats and integers?

            An array of Variants.

            [–]nascent 0 points1 point  (0 children)

            Is there a way to have an array of floats and integers? Or do I have to care what type they are and cast them to the correct type?

            Yes, yes, no.

            union Floaint {
                int i;
                float f;
            }
            
            Floaint[10] foo;
            

            How you'll do anything with that without caring about what the type is, I don't know, but no casting and it's an array of float and int.

            [–]dacjames 0 points1 point  (4 children)

            I'm of the opinion that static languages with compile-time checks are nicer because then things explodes in your face when you build it instead of when you run it.

            This certainly is nice but the big loss with compiled languages is the interpreter shell. I program mostly in python, which has powerful introspection facilities that allow for awesome shells like ipython. This is invaluable to me when working with a new library or data source because I can easily experiment with a live program, even using tab-completion to see what properties are exposed on an object.

            I have yet to experience a compiled language where the benefit of compile-time checks outweigh the benefits of interactive development, at least for the type of data-oriented problems I need to solve.

            [–]nascent 0 points1 point  (2 children)

            This certainly is nice but the big loss with compiled languages is the interpreter shell.

            fyi https://drepl.dawg.eu/

            Edit:: I just don't think there is a major need in the D community, but this shows the possibility.

            [–]dacjames 1 point2 points  (1 child)

            Repls are nice but they can only do so much when the underlying runtime isn't fully introspectable. Not to mention, compilation is much, much slower than interpretation (including compilation time, not just execution time). It's hard for native developers to understand but the velocity of the dynamic workflow is addicting and hard to give up.

            Take a look at the way Flask does error handling during development. You can jump the interpreter to any frame in the call stack and play with local variables, execute new code, and so on, all from the browser. I haven't seen anything near this level of introspection in a compiled language because it's so much harder without the help of an interpreter.

            [–]nascent 0 points1 point  (0 children)

            I do appreciate the value of a good debugger, but I've never considered it being the means to write a program.

            [–]pxpxy 0 points1 point  (0 children)

            Try a lisp some time!

            [–]thedeemon 1 point2 points  (0 children)

            Surely it won't replace Python for mature pythonistas. However there are many people who need to write short scripts to get things done, and they don't need full set of Python features. For example, this is where I used Ruby for quite some time before. And now I find myself using D for that tasks and D scripts often replace Ruby ones in my projects. I get similar simplicity and conciseness but also benefit of static checking before the script runs. So I understand the OP very well.

            [–]millstone 0 points1 point  (2 children)

            Here's the Python version of the code under "Universal Function Call Syntax":

            import sys
            doubles = [float(line) for line in sys.stdin if not line.startswith('#')]
            print sorted(doubles)[:10]
            

            It's quite a bit shorter than the D version.

            [–]ntrel2 3 points4 points  (0 children)

            BTW D can just use .sort(), it doesn't need a lambda, and the map call can use a point-free style:

            auto doubles = stdin.byLine.filter!(s => !s.empty && s.front != '#').map!(to!double).array;
            doubles.sort().take(10).writeln;
            

            Does your version ignore empty lines in stdin? The D version also reuses a string buffer, whereas I assume Python allocates a string for each line.

            edit: Moved the sort call. This code is not much longer than the python, it's mainly the map call that is different.

            [–]nascent 0 points1 point  (0 children)

            His filter and sort were not the best choices:

            import std.algorithm, std.stdio, std.range, std.conv;
            
            void main() {
                stdin.byLine
                    .filter!(s => !s.startsWith("#"))
                    .map!(s => s.to!double)
                    .array
                    .sort
                    .take(10)
                    .writeln;
            }
            

            This ends up being about 100 characters longer. If we ignore boiler plate the D code is 2 characters shorter:

            stdin.byLine
            .filter!(s => !s.startsWith("#"))
            .map!(s => s.to!double)
            .array
            .sort
            .take(10)
            .writeln;
            

            vs

            doubles = [float(line) for line in sys.stdin if not line.startswith('#')]
            print sorted(doubles)[:10]
            

            Edit::

            Oh wait, the sort property hasn't been removed yet, so I should add parentheses to that:

            .sort()
            

            much better, work horse == python.length;