3 ms·
> Dynamic arrays are only few lines to implement. There are different ways to do them, and no matter how, there will always be some problematic aspects. Not sur
by FeepingCreature 5y ago
> Dynamic arrays are only few lines to implement. There are different ways to do them, and no matter how, there will always be some problematic aspects. Not sure why you would want to choose one particular implementation and elevate it to a higher status.
Just having a default in the language is insanely useful. I can only appeal to experience here (with D, which has built-in arrays), but I never want to be without them again. This goes doubly for my language, where dynamic arrays are actually a bit involved due to the need for slices, refcounting and capacity tracking for the doubling strategy on append. Not something you want to reimplement everywhere.
> It's ugly and inexperienced users will write bugs using it, but it's also tremendously useful. You mentioned quasiquoting as an alternative, but I'm not positive that it works as a preprocessor replacement for a language that lacks the "homomiconity" of LISP. Are there examples that show it works?
As an example, something like
#define SQUARE(X) ({ typeof(X) x = X; x * x; })
could in a language with macros (and a better function macro syntax than I have at the moment :p) be rewritten as
macro SQUARE(X) ({ typeof($X) x = $X; x * x; });
Which has the exact same effect, but does not suffer from the C preprocessor problems caused by string/token interpolation. Also, errors can be easily and cleanly attributed to the actual location they occur, because SQUARE's nature is a parse tree, not a token list.
As for macros like `#define BEGIN {`, I consider it an advantage that they don't work. :)
- jstimpfle 5y ago> refcounting and capacity tracking for the doubling strategy on append. Not something you want to reimplement everywhere. Not something I want everywhere, in the first place. Especially refcounting. > macro SQUARE(X) ({ typeof($X) x = $X; x * x; }); Yes, stuff like that works, but only if your replacement body is a fully formed syntactical expression. Such a "syntactical macro" system can be nice because it's safer, and it's applicable in _most_ cases. But not for all - there are many situations where the full generality of C preprocessor macros (which are lexical / "token list" macros as you say) are useful. X-macros might be the example that I use most, and that wouldn't work with syntactical macros. Another application are macros around for loops, like FOREACH_FOO(...) or SCOPED_LOCK(...) for example. All dirty hacks that I like to use from time to time and that I prefer immensely to systems built in to the programming language and lead to immense complications in the language. Another example would be partial lists of any kind, for example lists of compiler intrinsic attributes #define FOO_API __attribute__((what1)) __attribute__((what2)).. String interpolation is probably not in scope for a syntactical macro system either printf("Hello from " PROG_NAME " version: " PROG_VERSION "\n"); Another example, but you might sneeze at that one - my current project is a pile of macro hacks, it contains a lot of stuff like #define DEFINE_BUILTIN(bkind, bname, num_args) else if (is_identifier(t->t_name.buf, bname)) \ ... #define PREC(t, p) case t: prec = p; break; It's more "temporary" stuff that will need factoring into data tables where there are extensions, but a lot of it is just good enough and will never be touched again. -- Expecting code to be so clean, always from the beginning, that all macros one would need ever can always be defined by syntactically complete expression bodys, that is not going to work. Just like there have been many attempts at getting rid of text-based programming languages and moving to structured (syntactical) editors - that hasn't panned out either.
- FeepingCreature 5y ago> Another application are macros around for loops, like FOREACH_FOO(...) or SCOPED_LOCK(...) for example. This is the exact case where full macros can deliver a lot more power, more cleanly, than preprocessor macros. In this case, in Neat, you'd probably use a full parser macro rather than a call macro, and you could recognize arbitrary syntax, without allowing you to violate parenthesis order like C does. Your macro can do whatever it wants, but it cannot conflict with other, preexisting syntax, such as (in C) defining half a loop or half a variable declaration. This way, it can fully own its syntax. > Expecting code to be so clean, always from the beginning, that all macros one would need ever can always be defined by syntactically complete expression bodys, that is not going to work. Correct, however the example syntax was a simplification of macros. Fundamentally, there's no reason a macro shouldn't be able to do anything that the compiler itself can do.