Re: NEWBIE - generics issue
I get no compiler error for your example (maybe there is some problem in your full code), just a run-time error from dispatcher, because you didn't allocate the object for `a` (via `new`, as the variable is of reference (pointer) type, not object itself). The full code: type Something = object a: int special: Special Special = ref object {.inheritable.} SpecialisedTA = ref object of Special abc: string SpecialisedTB = ref object of Special def: string import json method foo(s: Special, node: JsonNode) {.base.} = assert(false, "Kinda abstract") method foo(s: SpecialisedTA, node: JsonNode) = s.abc = node["abc"].getStr() method foo(s: SpecialisedTB, node: JsonNode) = s.def = node["def"].getStr() var a = new SpecialisedTA var jsonNode = parseJSON"""{"abc": "5", "def": "7"}""" echo jsonNode foo(a, jsonNode) echo a.repr Run Wrapping your code in posts with "```nim" and "```" makes it highlighted.
Re: Macro - whileSome: none:
If you want the second keyword be "none" and not "do", you can use 2 templates/macros and a variable to pass state between them, like: var whileSomeNone: bool template whileSome*(condition: typed, body: untyped) = whileSomeNone = condition if whileSomeNone: while true: body if not condition: break template none*(body: untyped) = if not whileSomeNone: body Run No check is performed here that `none` follows `whileSome`, as downside. May be used nested: import whilesome var a = 3 # set to >=7 for "none" branch var b = 7 proc c: bool = return a < b whileSome(c()): echo a inc a var i = 0 # set to >=3 for "none" branch whileSome(i<3): echo "i=", i inc i none: echo "i >= 3 initially!" none: echo "No items to display!" Run
Re: NEWBIE - generics issue
`when` is resolved at compile-time, at run-time you get just one of two branches, which already knows what field to read from JSON and where to put it. So if you explicitly pass strategy (type disambiguator) as compile-time known (static) argument, a proc with `when` is the simplest and most performant way. With those `foo` 's, in my example above `Something` type was not used and the variable was of a specialised type, so methods can be replaced with just procs too. You'll need methods if you want variable of a general (`Something`) type and no explicit disambiguator: # using the code from previous example with `foo`'s, except the last paragraph # prettifying echo'ing method `$`(s: Special): string {.base.} = assert(false, "Kinda abstract") method `$`(s: SpecialisedTA): string = "[abc: " & s.abc & "]" method `$`(s: SpecialisedTB): string = "[def: " & s.def & "]" proc `$`(s: Something): string = "[a: " & $s.a & ", special: " & $s.special & "]" var jsonNode = parseJSON"""{"abc": "5", "def": "7"}""" var a: Something a.a = 3 a.special = new SpecialisedTA # `a` can store either `SpecialisedTA` or `SpecialisedTB`, # and you don't pass any explicit disambiguator to `foo` foo(a.special, jsonNode) echo a# => [a: 3, special: [abc: 5]] a.special = new SpecialisedTB foo(a.special, jsonNode) echo a# => [a: 3, special: [def: 7]] Run
Re: Globally-invoked macros
> they make semantics clear in one place in the source code For this reason per-module macros invocations should maybe be restricted to the top of the module (as `#? strongSpaces` is now), with only imports and static code allowed before them: the user anyway has to look at the module's top for imports, to know how to read/understand the module's code. But anyway for now imports are allowed throughout the modules, to read a part of it the user has to look through all preceding top-level code. The proposed per-module macros are supposed to be invoked only at the top-level too, not much difference with imports. > Who gets to dine first? The macros are invoked in the order in which their invocations follow, the user is in full control, the macro's author doesn't and shouldn't decide this. It's the same with today's per-block and per-routine macros, again no difference.
Re: Globally-invoked macros
Your points are generally correct, just don't fit to Nim as it is - they are not satisfied already. > Imports just add symbols from other modules to a module Not in Nim. You yourself already mentioned converters - code starts to work differently just by importing a module. Add to this methods - just by importing a module you change dispatching, already existing calls take different paths, it's not mirrored in your code. But why methods - just regular procs do the same, you can add a better (more specific) overload match by an import and change logic of an alredy working code. I.e. you don't add any calls for it - just an import. Concepts: their matching is changed by just adding symbols. `mixin`: new symbols are taken into account, just their adding changes how the code works. Changes may be not less at all, than with per-module symbols, the latter just adds a friendly syntax. Scarcely these are all the features that change program's logic just by addition of symbols. These all of coarse lessen code's evidence, for that increasing its expressiveness, and so far the latter is Nim's virtue.
Re: Globally-invoked macros
Btw, there are nice hints for term rewriting macros on their matches in compiler output, the like may be displayed for such macros, adding a bit explicitness.
Re: Globally-invoked macros
> As for term rewriting macros: AFAIK they are meant for local optimization and > code adaption, not for behavioral changes. But they still can say turn _2_ to _3_. :) And these macros too are not meant to change behaviour counter-intuitively (why would one want?), say in the @quelkef's example - just to introduce cleaner/saner (subjectively), non-repetitious recursion syntax. By efficient is rather meant, that it produces binaries not less performant, than C's, and programmers efficiency much comes from expressiveness, but well. :) * * * I put it not clear in that post, those features, affected by currently defined symbols, are much more implicit, than this one - they are applied automatically just by import itself, you don't have any triggering code in your module. And these per-module macros are applied manually, you see them in the module, at least prior to the place, where they are applied, or closed to module's top, with that restriction in force. So this feature is much more obvious, it's rather on par with imports and filters.
Re: Globally-invoked macros
Another (a more explicit) way would be to have possible to deal with modules the same as with routines or blocks in macros, and to have a `currentModule` symbol. Then the same could be expressed with `a.implementRecur currentModule`, with the usual syntax, the same as `a.implementRecur: ...` (for blocks) and `a.implementRecur someProc`.
Re: Globally-invoked macros
> I think that'd be strange; ... I think that'd be strange; ... It feels like I > should end up with the macro output followed by the original 20 lines of code. Yes, `wrapWith` looks more intuitive.
Re: Globally-invoked macros
> Which one is it, more obvious than imports or on par with them? You just > reminded me that imports can change the behavior of local code It is more obvious than features are listed in one of my previous posts (i.e. converters, overloads, concepts, `mixin`, term-rewriting macros) - they all are enabled just by an import, you don't switch them on even by a single line of code in the module, which they change. They are on par with imports (imports themselves, not those other features triggered by them) and filters, in that they both are represented by a single line in the module which they change (are visible to the user).
Re: Globally-invoked macros
Say you're using [NimContracts](https://github.com/Udiknedormin/NimContracts). You add `import contracts`, then yet for any procedure using it you add the pragma `contractual` (but quite probably most procedures in the module will need it), or wrap blocks of code in `contractual:` with indentation. Yet the features of NimContracts are used by introducing inner blocks with `invarinat`, `ensure`, `body`, `require`, they are visible already, `contractual` there's usually needed only technically, not as a hint for the user. This is probably the same with most the like libraries, that is those, which need surrounding context for their features to work.
Re: Proposal for Forum Improvements
Answered at GitHub.
Re: Globally-invoked macros
> I realized that there's no technical reason to disallow wrap statements from > appearing in any statement list Yes, it may be of much use. Say, though to wrap a procedure's body in a macro you can wrap the procedure itself with a pragma and in the macro to get its body, the macro may be of general use and expect just a statement list; and you then required either to modify the macro code and introduce a special case (much undesired), or to introduce an intermediate macro. Yet there are statement lists for `if`, `while`, ... > Wrap statements are allowed after templates and macro definitions so that a > wrap statement may use a macro located in the same module as it appears in I think compile-time procedures, constants and `static` blocks (all the compile-time stuff) should be allowed too, they all may be in the required background for the macro. > so that `body.macro(arg)` can be idiomatically used No, such macrso are usually called `macro(arg): body`, so your proposed order is optimal. > If anyone can think of anything good `processwith` is closer in meaning, though longer.
Re: Globally-invoked macros
I'll try. :) Sorry, it then becomes long. Situation: one has macro, which takes a statement list, and a procedure, which body (contents) needs to be processed with that macro: macro m ... # it can be used so: m: echo "smth" doSmthElse() proc p = ... # We want to apply `m` to these statements Run Instead of this macro m ... # expects a statement list as the argument proc p = wrapwith m ... Run one can principally do proc m2 ... # rewritten to take a procedure as the argument proc p {.m2.} = ... Run . But if `m` is not created for this specific use (to process `p`), but imported from somewhere, or is used already for blocks of code (`m: ...`), then it cannot be just changed to take a proc instead. Even if it's newly created, making it to work with both proc p {.m.} = ... # and m: ... # stmtList Run is a complication. One can instead write yet another macro, which takes `p`, gets its body and passes it to `m`, which is again an extra burden for user. So, then, if `wrapwith` is allowed within inner levels, including inside procs, then one can just use an existing macro, which takes a statement list (i.e. is supposed to be used as `m: stmt1; stmt2`), or write just one macro for both cases, expecting just a statement list in it: import theModuleWithThatMacro m: echo "a statement" echo "yet another" proc p = # {.m.} would not work, `m` doesn't expect a proc wrapwith m echo "m gets this statement" echo "together with this, in a statement list" Run So +1 for allowing in any statement list.
Re: Winim - Nim's Windows API and COM Library
Much thanks for the new version!
Re: Why is it needed to discard void return value from c function?
You can call them without `()`, when it's clear otherwise, that it's a call. Say, in command syntax with arguments: `a b` (means `a(b)`). In dot syntax: `b.a`. In just `a` on its own `a` represents just the proc itself, so that you can send it as an argument to other procs or save to a variable, like: `mySeq.map toUpperAscii`, `toUpperAscii` is not called here, but passed to `map`. Or: proc x(s: string) = echo "[", s, "]" var y = x y "z" Run And as just `quit` returns the proc itself, it is an expression ('None' is its type), not a statement.
Re: Return SUM types from proc
Supports, if the sum type can be treated as generic, i.e. if compiler can decide at compile-time for each use of the sum type, which concrete type will it substitute. Like in using such a proc: proc test(arg: static[int]):Ret = when arg < 0: return A(a_value:arg) else: return B(b_value:arg) But the argument, on which the type choice is made, is static, that is, compile-time: really 2 different zero-argument procs will be instantiated by compiler for `test(10)` and `test(-5)`, and their arguments should be able to be evaluated at compile-time.
Re: Should/can we get explicit concepts?
Neither a feature or a bug. These are just different ways of abstraction, each of which can be preferrable in some situation. I like concepts (that is, implicit ones, as they are) too, I'd not want them just to be replaced with interfaces (explicit concepts), the proposition is of having both ways. The purpose of interfaces is to express programmer's intention; not what concepts are intented to. About Go's interfaces: I don't know this language, I just heard that something very different is called by interfaces in it, just sharing the same word; probably it's something nearer to concepts; better not to compare things as respective just because of wording, this is why I've mentioned explicitly Delphi (Object Pascal), Java, PHP and C# (probably there are more) as having this feature. Still there is some difference between interfaces in those languages and explicit concepts, as proposed for Nim: those are based on dynamic dispatch; this not what really needed, procs can be instantiated statically per concrete type, the same as with implicit concepts (as now). So they are still the same concepts in all respects, except: * they don't match types, which were not declared explicitly as satisfying these explicit concepts; * obviously, there is a way to declare for a type, that it satisfies some explicit concept, like proposed `satisfies MyConceptName` in type declaration, or it can be `implements`, or a pragma (`{.satisfies: MyConceptName.}`); * obviously, some addition in concepts syntax, to mark it as explicit: again, proposed `explicit` before `concept` keyword, or a separate keyword `interface`, or a pragma (`type X = concept {.explicit.}`).
Re: proc(t: typedesc): var t -- expected 'None' error
I don't know how to make it work with `: var t`, maybe a bug or not supported; works with `template getMutableVal(key: int, t: typedesc): var typed =`. I assume you need `0.getMutableVal(bool) = false` syntax, otherwise you can pass types as a generic parameter (`proc getMutableVal[t]...`), that works with `: var t`.
Re: Mutability of loop variables
You can no way modify the string via this iterator. The easiest way: split it into a sequence via the same-named proc (just save it into a variable), and then in the `for` loop use `mitems` iterator on it, it allows modifying. Then `join` the sequence into a new string. Or w/o modifying: use a variable in the loop (`var s=line.strip`), do any processing, then concatenate into a new string, defined empty before the loop. To syntax-highlight Nim code in the forum posts wrap it like in the hint below the textarea.
Re: Windows Subclassing
Like that: `someType(someValue)` (or, what's the same, `someValue.someType`) means "convert this value to this type", and compiler should consider these types (that of the value, and to which you convert) as compatible to allow this operation, and it can use an additional transformation for this (you can define it creating a `converter` for these types). `cast[someType](someValue)`, on the other hand, means just "interpret this value (its bits sequence) as being of such a type"; it doesn't involve any compatibility-checks nor transformations of the value - you relief the compiler of responsibility for validity of type change; so you can convert between formally incompatible types - just make sure, that the cast really makes sense (as in this instance - one type is pointer, the other - a procedure - is really a pointer too). I think you can find it in the manual, and possibly it's better described there.
Re: Bug with generic methods?
> Please note the biggest problem of inheritance-based interfaces: you cannot > add one to a type already in existence when you define the interface Certainly you cannot; that is the point - not interfaces state, what types satisfy (implement) them, but the other way round, types state, what they implement, and interfaces can only restrict, what types can state that (say, providing signatures for required procs); not satisfying the interface's restrictions results not in rejecting for the type to be considered as being of that interface, but in a compile-time error. E.g., supposing concepts-syntax for interfaces: type I = interface x p(x) T = distinct int implements I # p(t: T) = discard This should result in a compile-time error, unless the last line is uncommented. And at the same time type I = interface x p(x) T = distinct int proc p(t: T) = discard echo T is I # -> false , because `T` here is not intended to be `I`.
Re: Wrong indentation in IF expr
Probably expressions are intented to work with indentation too, so probably will do some day, so parantheses and semicolons then are just a practical workaround for now, so aren't documented.
Re: Are array types that differ only in index boundaries different?
Not a run-time conversion is meant (that there are given 4 bytes for "3" and then at run-time it's transfered into 1); just the type for `3` literal is `int`, and of the value, created from it for x, is `int8`. And that "treatment" is implicit. ׃) You expressed it more exactly.
Re: Containers of generic types
Probably you're asking about what here is discussed: [https://forum.nim-lang.org/t/3150](https://forum.nim-lang.org/t/3150); that is, on storing different (concrete) type values in one container. You have to choose between casts, object variants, refs to objects + dynamic dispatch (methods), maybe something else, depending on your task. Just generics/concepts by themselves cannot be instantiated and so stored in containers, because of not having any run-time representation (not just now, it cannot be otherwise). With just creating generic containers, storing values of one type for each instantiation, there's nothing special to do: just `type MyContainer[T] = seq[MyObject[T]]` and the like.
Re: Do notation without parentheses
I tested with 0.16.1. With current 0.17.1 indeed the last example compiles, and the first fails with redifinition. So now `do` means something different, I don't know what. May be a bug, maybe a special case of blocks with no new scope. Otherwise blocks open new scopes, and this for example did compile and still does now: block: var x = 1 echo x block: var x = 2 echo x
Re: Been away for 9 months. What changed? Need some help to get back on track.
> better concept system from @zahary? Yes, [docs](https://nim-lang.org/docs/manual.html#generics-concepts) (except VTRef).
Re: Custom memory allocator and memory region
While direct support for seqs and strings is not here (it's planned, according to the manual), you can wrap them in objects. type MySeq[T] = object data: seq[T] Cuda = object var foo = cast[ptr[Cuda, MySeq[int]]](alloc sizeOf(MySeq[int])) foo.data = newSeq[int]() foo.data.add 7 echo foo.data[0] or with constructor and wrapped procs proc newMySeq[T](size = 0.Natural): Cuda ptr MySeq[T] = result = cast[ptr[Cuda, MySeq[T]]](alloc sizeOf(MySeq[T])) result.data = newSeq[T](size) proc add[T](s: Cuda ptr MySeq[T], v: T) = s.data.add v proc `[]`[T](s: Cuda ptr MySeq[T], i: int): T = s.data[i] for more convenient usage var s = newMySeq[float]() s.add 5 echo s[0]
Re: Convert tuple into a Object
Why they should be truncated, if they are of the same size? And your macro assigns fields by names... That is, it in the end doesn't allow you to write like `createRef(O, (5, 6.6, 7i8, 8i8))`, just providing a type and values.
Re: Differences: Object variant vs static conditional fields
To store defferent types values in one seq with no (when values are of the same size) or minimal memory overhead, and no CPU overhead, one has to use casts (`cast[]()`), obviously at the coast of non-distinguishing their types; that is, it just has to be known, at what index what type is used, or items have to be used disregarding their types (say, for storing in files, as is). Runtime type differentiation necesarily involves overhead, generally nothing less than with object variants.
Re: Convert tuple into a Object
An unsafe but fast and clean way - just to cast your tuple to your object type: proc createRef(typeinfo: typedesc, data: tuple): auto = result = new(typeinfo) result[]=cast[typeinfo](data) Be aware you should provide a tuple of values of needed types, or the same in size, and not just compatible: type O = object x: int y: float z: int8 q: int8 let r = createRef(O, (5, 6.6, 7i8, 8i8)) echo r[] In this example, if you provide the 3rd as `int`, not expected `int8`, you won't get the 4th item of tuple into your object - `7` literal will pass an `int` value (32/64 bits), setting `z` and `q` fields to `7` and `0` respectively.
Re: Partial casing is foo_bar
_OderWat:_ {. pure .} could be used for the enum in your example, no renaming then needed. * * * I'd like some special character to be allowed at the end of identifiers, be that underscore, or (better) apostrophe (`'`), or something else present on keyboards. `x`, `x'`, `x''`, or `x`, `x_`, `x__`, are convenient to use for related local variables (apostrophes are easier to distinguish, and don't look ugly). And I like style-insensitiveness. Maybe a per-module directive (pragma) for prohibiting using the same identifier in different styles throughout that module could satisfy some of people, who have troubles with this. Even with that option enabled the possibility remains to use identifiers from other modules (of other authors) in preferred style. Say, to use `x_y` from another module as `xY`, given that it's used only as `xY` in this module. And the usual behaviour (any style allowed) remains, when the option is not enabled.
Re: Containers of generic types
Storing values of different types in a container, in arbitrary order, and handling them then appropriately to their types at run-time, necessarily means run-time dispatching (detemining type of each value in the container at run-time), that is, something you can program - there's no restrictions on run-time behaviour of your programs, made with Nim. At low level, your values have to have some type information stored along with them. To not do that manually (though you can), there are [object variants](https://nim-lang.org/docs/manual.html#types-object-variants) in Nim, exactly for this task, the same as in Pascal, or like "struct with union inside" in C terms; they use memory for the largest in size of branches, that is, use the same storage space for different, even different-sized, values. Yet, for objects, you can inherit them from one base type and use [methods](https://nim-lang.org/docs/manual.html#multi-methods) instead of procs - they distinguish types; this same way run-time dispatched interfaces work. These all don't use casts or any unsafe features. The reason for mentioning casts was that in some cases they allow to manage without run-time overhead for this task.
Re: Bitwise operation problems.
Nothing wrong here with `and`. Probably just what you want is `or` (if you want to combine 4 values with disjoint bits into 1).
Re: How to transform compile time into runtime data
An easy workaround to not add `genericCall` \- passing `procs` as the first argument: # remote.nim, only changes # making exported var registeredProcs* {.compileTime.} = newSeq[string]() # ... proc genericCall*(procs: seq[string], id: string, x: float): float = # ... # user.nim import remote as remote_module proc userSquare(x: float): float {.remote.} = x * x proc userCubic(x: float): float {.remote.} = x * x * x const procs = registeredProcs discard procs.genericCall("userSquare", 1) discard procs.genericCall("userCubic", 1) Maybe you can make `procs` in `genericCall` bound to the current module's symbol, then you can get rid of passing it as an argument.
Re: Bug with generic methods?
Exactly, and the same for interfaces (in Delphi/Java/PHP,... sence) (it was often claimed here that they are of no need for Nim, because concepts are better interfaces).
Re: Compile error when wrapper type(...) with template
The issue with `foo2` and `foo3` is one and the same: when called from a generic proc, untyped-arguments templates in them won't be used for type annotations. Your `getType` is not used then, so `macros`'s one used, if you import it, what you can see by using explicit `your_module_name.getType` \- then `import macros` will change nothing.
Re: generic template
Yes, that makes sense. This seems to work: template constructFoo*[T1, T2](): Foo[T1, T2] = implConstructFoo(typedesc[T1], typedesc[T2])
Re: Wrong indentation in IF expr
If you generate code automatically, then just flooding a little exptressions with parentheses may be the easiest way (parenthesize all subexpressions, not statements). Yet add semicolons after statements in expressions. E.g. your code works in the following version: proc strsubsmart(s: string, start: int, fl0wlen: int): string = if start >= 0 and fl0wlen > 0: substring(s, start, fl0wlen) else: var slen: int = strlen(s) var trueStart: int = ( if start >= 0: ( start ) else: ( var ss: int = slen+start; if ss >= 0: ( ss ) else: 0 ) ) var trueLength: int = if fl0wlen > 0: fl0wlen else: slen+fl0wlen-trueStart substring(s, trueStart, trueLength)
Re: How do fellow new comers deal with optional parenthesis dropping?
_@RedFred:_ +1
Re: template and proc with same name
That's not because templates have priority over procs, but because of argument types. Say, if you have 2 procs, 1 taking T and another - any (procs cannot take expr), then the 2nd (with any) will be called. The same if the 1st (with T) is a template, or if both are templates, or if both are templates and the 2nd is expr. In all these cases not "template vs. proc" determines the choice. Though it seems to me that T should be preferred over expr as less specific.
Re: Pascal type to nim
Nim's object variants are from Pascal, they are what you need. Smth like: Data = object {.packed.} case b: byte of 0: AsChannelStatus01: TChannelStatus01 of 1: AsVoltageList: array[0..127, single] # ... else: discard
Re: Community name?
Nimians. Sounds like a nation. Nimrodites. Nimologists - only for coredevs.
Re: template/generic instantiation from here
This hint should accompany some error message. But the example works well for me (no such message).
Re: Should/can we get explicit concepts?
Yes, seems to be mostly fixed. That time I could not create (or populate) dynamically allocated values at compiletime, like sequenses, tables, ptr/ref'ed values. As I've just tested, now sequenses, tables and strings work as expected (pointers though seem to not work, silently; probably just all unsafe features are disallowed, like yet casts and FFI). The idea to begin with then was to create an extendable list of association of interfaces to types, implementing them (interface#1 => (type#1, type#2, ...), ...), then to append items to it in `implements` macro, and in a concept's body to check that the type tested is in the list for that concept.
Re: How check if expression has a type without triggering compilation failure
> template filter(expr: untyped) = > > > when compiles(expr): > when expr is seq[bool]: echo "bool" elif expr is seq[int]: echo "int" > else: echo "something else" > else: > echo "can't compile" > > filter(a + b) It seems code-highliting is broken.
Re: Base type for all procedure pointers
Why not to use `pointer` instead of `array[8, byte]`. Will Work for both 64 and 32 bits.
Re: Disable debug for specific function
Try pragams like `{.checks: on.}`/`{.checks: off.}` and the like (there are ones for specific checks), better via `{.push checks: off.}` and then `{.pop.}`, so for the rest of the code checks are still contolled by configs and command line. For the 2nd, try `GC_disable`/`GC_enable` (inside the proc).
Re: Exploring namespaces support in Nim
**@lltp**: I've meant, if `type(A'M*A'M) == type(A)`, then what is `type(A:T1'M*B:T2'M)`?
Re: BASS lib
Don't know whether a bug in the DLL or a wrong usage: the loop in the example is executed successfully 65 times and the program fails on the 66'th call of `BASS_ChannelIsActive`. The same with different sleep times, so with bigger sleep times it plays longer before failure. The same for different files (MP3 and OGG). Yet in the example parentheses are missing for `BASS_Free`.
Re: complex statement requires indentation
Updated. Yes, can be chained, updated the examples too. > Also let's mention some keywords Don't know... "empty coalescing"?.. "double question"? Probably it can be found by just 2 words "coalescing operator" when combined with "Nim".
Re: Min: a Nim-based minimalist, concatenative, functional REPL & script lang
**Note to admin**: that post is a full copy of the first (_Libman_'s) post, after the first 2 words.
Re: What are you writing using nim? :)
Web-crawling/parsing, automation scripts.
Re: Macros and imports
You don't need anything special for this. Just the usual rules apply for cross-module use: if the macro is defined in one module and the procedure created by it is used in another, then just mark with `*` (as exported symbol) either the macro itself (if it will be called in the second module, so that the procedure will be created in that) or the procedure (if the macro will be called in the first module, in which it is defined - then you don't need to import the macro, instead the proc to which it expanded). Happy New Year to everyone!
Re: Partial casing is foo_bar
_OderWat:_ There is nothing wrong with Basic or simplicity, just each language has some its characteristic feature, its accent. There cannot be C without pointer arithmetic, or Java without OOP, Basic without simplicity, Haskell without functional programming stuff, be each of those accents considered as good or bad. Of course Nim can go on without case/style-insensitivity, it's not such a fundamental feature for it (not like, say, macros or concepts). But striving for overall simplicity would mean to get rid of 99% of Nim (macros, templates, converters, pragmas, ..., lots of stuff) and to create quite an opposite language - then why to begin with Nim. And C++ can be here as an example. It started as a more powerful (more complex, more expressive) kind of C. Now lots of people use C and lots of people use C++, each choosing among simplicity and expressiveness, and every of two choices has its pros. But could C++ exist now, were it decided to be simple? It needed to be somewhat different (especially from C) for its existence to have sense.
Re: Why does this not compile, and how can I fix it?
You can fix it by disambiguating the passed proc name, `isDigit` -> `module_name.isDigit` (you see in the error message, that this is the cause). Yet you can turn the corresponding parameter into `untyped`.
Re: Defining an array inside a tuple
Arrays are not special, just having them of length of 100 you won't want to initialize them by a literal, the same for seqs. type GlyphArray* = array[3, int] type TextBuffer* = tuple position: tuple[ x : float, y : float ] cursor : tuple[ row : int, col : int ] glyphPositions : GlyphArray linePositions : seq[tuple[ start: int, stop: int]] text: string var my_text : TextBuffer = (position: (25.0, 25.0), cursor: (0,0), glyphPositions: [3,5,7].GlyphArray, linePositions: @[(0,0)], text:"") echo my_text.repr
Re: ref object or object with ref field
> For dynamic dispatch to work on an object it should be a reference type as > well. That is, this will call RootObj's method, not A's and B's (continuing **Krux02**'s example): var values : array[2, RootObj]= [a, b] for p in values: p.foo
Re: Should/can we get explicit concepts?
I consider this possibility a very useful even without additional checks (those in the concept body), like of existence of procedures defined for the type with stated signatures and the like, exactly because the programmer explicitly declares the purpose of his type and what can be done with, what functionality is really supported by the type. I think this explicit promise/contract is the main point for interfaces in Delphi, Java, PHP, C#, and signature checking is additional to that. I'll try to make it more visual: type Browser = concept type b proc goTo(self: b, url: string) proc back(self: b) proc forward(self: b) proc makeSomeStuffWithABrowser(br: Browser) = br.goTo("http://www.nim-lang.org/";) # creating a concrete type satisfying the concept type MySimpleBrowser = distinct int # whatever it would be proc goTo(self: MySimpleBrowser, url: string) = echo "going to " & url & " with MySimpleBrowser" proc back(self: MySimpleBrowser) = discard proc forward(self: MySimpleBrowser) = discard # using it var sb: MySimpleBrowser makeSomeStuffWithABrowser(sb) # it works, well; it should # here we don't want to define another Browser, just an unrelated type; maybe in another module type FileManager = distinct int proc goTo(self: FileManager, path: string) = echo "going to " & path & " with X" proc back(self: FileManager) = discard proc forward(self: FileManager) = discard var fm: FileManager # and here by accident... makeSomeStuffWithABrowser(fm) # works too :( Lando's suggestion is perfect in my view, if not to restrict it to object type - it can fit equally well any types, as concepts do. It can be seen like a type class (like e.g. `SomeReal* = float|float32|float64`), but extendable and with inverse binding: created empty and populated with concrete types at their definition site. Like: type X = explicit concept c # ... # X here matches no concrete types, regardless of checks in the concept body type Y = distinct int satisfies X # conditions in X concept body are checked, # compile-time error, if not satisfied; # Y is added to the list of implementations for X type Z = distinct int satisfies X proc p(x: X) = discard # here the same as p(x: Y|Z) Regarding wording, `explicit concept` and `satisfies` seem to be not worse than usual `interface` and `implements`, especially taking into account distinctions; just for people coming from those languages those terms may be more familiar; maybe `explicit concept` will be easier to understand to others. Regarding implementation, macro vs. built-in: I wanted to implement such a thing some (long) time ago via macros and concepts and was faced then with some VM limitations; maybe they were eliminated from then. The intended syntax was (for simplicity): type X = ... implements X, I
Re: Access procedure arguments from a macro when the procedure is called
> it's more readable than using `setterProc.params[2][0]` You don't have to use `setterProc.params[2][0]` with your first approach (with `quote do`). Just `value` works - identifier will be resolved in the procedure being transformed, not in macro. Oppositely, to use the macro's symbol, you have to quote it with backticks. So what you had to change in your first example is to add backticks around `limit` (like in _Krux02_'s example), using `value` as is (just with `.len` appended).
Re: Error: invalid indentation
Yes, `object` is a value, `ptr object` is a non-garbage-collected pointer to an object, `ref object` is a garbage-collected pointer to an object, `object of ...` is the way to inherit, to be combined with any of the previous, and after any of that a list of fields may go. `RootObj` is not smth special and built-in, it's defined in `system.nim` (like many other things, read that module for better understanding) as `type RootObj* {.inheritable.} = object`, a predefined root for inheritance hierarhies, but you can create separate hierarchies (your own roots) the same way, marking your object type as `{.inheriatable.}`. `Class3 = ref Class1` \- values of this type will be double references: references to referenced (`Class1`) subtype of empty objects (`RootObj`).
Re: Mutability of loop variables
Gives "redifinition of 'line'" error...
Re: passing references
Why not just echo "IS IT THE SAME? ", xobjref == result ? They are already addresses both.
Re: + won't take two different types
The way to go: type Addable = concept x, y x + y proc addit(a, b: Addable): auto = return a + b echo addit(12, 22.1) # -> 34.1 echo addit({1,3,5},{5,7}) # -> {1,3,5,7} * * * Yet you can explicitly convert arguments, this way you decide by yourself what type is the result: proc additF[T, U] (a: T, b: U): auto = return a.float + b.float proc additI[T, U] (a: T, b: U): auto = return a.int + b.int echo additF(12, 22.1) # -> 34.1 echo additI(12, 22.1) # -> 34 * * * Yet you can use implicit conversion: proc addit[T, U] (a: T, b: U): auto = return a + b converter x(x: int): float = x.float echo addit(12, 22.1) # -> 34.1 But it can make the code's logic more messy. * * * Below "submit" button there's a hint on making your code sample syntax-highlighted, makes reading easier.
Re: Type inference side effects
No, more implicit code of coarse is more compact (less letters to type and read), and this is exactly the reason for type inference to exist.
Re: Winim - Nim's Windows API and COM Library
WSH scripts in VBScript and in Nim are looking so alike, and so easy to translate! Thanks a lot!
Re: Code substitution with templates
Your syntax for macro's call is OK, your key-value pair is parsed as a call (`id` being regarded as a proc name, and `int` as statement list (block), passed to it). Now you need to write a macro, that can use it. In that macro you first assign to `result` the constant part of your type, and then add to it new nodes, via procs from `macros` module (search forum for examples). import macros template obj(tName: untyped): untyped = type tName = object fname: string age: int macro typeGen(tName, extraCode: untyped): untyped = result = getAst(obj(tName)) echo result.treeRepr # so you can see, where and how you add fields echo extraCode.treeRepr # so you can see, from where and you get them # and here you parse ``extraCode`` and add additional nodes to result[0][0][2][2]; # as is now, it will create a type with just 2 fields in the template typeGen(Employee): id: int
Re: Alternative to ugly generic class methods?
An alternative syntax for the procedures' signatures in the example, maybe is more to your taste: proc insert(this: var Dictionary, key: Dictionary.Key, value: Dictionary.Value) = ... proc find(this: var Dictionary, key: Dictionary.Key): Dictionary.Value = ...
Re: generic template
template constructFoo*(T1, T2): untyped = implConstructFoo(T1, T2)
Re: Cannot get name of type using typedesc
To the developer of "Run", in case if more browser support is needed: * "Access-Control-Allow-Origin" header is missing. It's needed for cross-domain requests for some [browsers](https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) and by [standards](https://fetch.spec.whatwg.org/#http-access-control-allow-origin) ("play.nim-lang.org" is regarded as a different domain). Firefox logs this: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://play.nim-lang.org/compile. (Reason: CORS header 'Access-Control-Allow-Origin' missing). It can be solved by adding response-header `Access-Control-Allow-Origin: https://forum.nim-lang.org` or `Access-Control-Allow-Origin: *`. * `code` parameter is not sent in requests, only `compilationTarget`, because `code`'s content is retrieved via `innerText`, which was not in standards until last year and is supported by Firefox only from that time. `innerHTML` is long supported and can be used instead, tags then should removed.
Re: Estimation of π using Leibniz series
At least so: `res += float([1,-1][n mod 2])/(2.0*float(n)+1.0)`.
Re: Exploring namespaces support in Nim
> from Module import type Foo Then maybe more explicit, something like: # module A type Person* = object user*: string age*: int proc `$`*(p: Person): string = p.user export (Person, `$`*(p: Person): string) as C # module B from A import C var x = Person(user: "Gustav Gans", age: 45) # $ for Person is called echo x Should be less work for the compiler, and any set of symbols can be combined, not just one type; so a module can be logically subdivided in any possibly overlapping parts, not affecting its inner structure anyhow.
Re: Nim VFS (virtual file system)
The idea ha nothing to do with decreasing download time or size, just easing dealing with sources, like treating the archive file as a directory, not having to unpack it first.
Re: complex statement requires indentation
Didn't think about laziness, indeed, it should. template `??`[T](val, alternative: T): T = const zero = zeroval[T]() if val==zero: alternative else: when compiles(val.len): if val.len==0: alternative else: val else: val * * * No, I don't know about talks. Youtube?
Re: Cannot get name of type using typedesc
"Run" button doesn't work for me, does nothing. JS enabled.
Re: Nim VFS (virtual file system)
This would be extremely cool! There was [some discussion](http://forum.nim-lang.org/t/937) on the forum about multiple modules per file, which could give some of the same advantages. And source-files archives treated as folders exist yet for Java and PHP (.jar and .phar).
Re: New high level ODBC library for SQL Server
@michael, are those indentations before `con.something` needed? If those are just value assignments to fields of an object, you should do that outside of a variable definition block.
Re: Thoughts on imports
> Writing `from blah import nil` for every import is ugly Probably less idiomatic/encouraged way should not be absolutely the same easy, as more idiomatic. So two extra words for the whole imports list should be OK, it could be like this: `from xxx, yyy import nil`.
Re: Concept[T] design question
Maybe I didn't get the point about `Copyable and Comparable`: this is an existing syntax for years and it works well AFAIK.
Re: Traybar support ?
That's simple enough, considering that's a C API, and not an genuine Nim's library. C doesn't have Nim strings, so you copyMem your string to its char-array; not such a problem. You can find all constants needed in `MinGW/include`, just make a text-search over the folder (matter of seconds); they are taken initially from there to `windows` module, and you can of coarse update it. Explanations of API functions and constants are in WinAPI Help, you probably have that with your programming tools; the docs are surprisingly good and easy-explorable, mostly you won't even need to search the web (though that is there too). I have it in hlp-format, there you enter in **index** `CreatePopupMenu`, and get the spec for the function you need, links to related functions (`InsertMenuItem`, ...) and **overview** button for the general information; a search and hierarchial contents are also there; that's really well-organized, not some mess of texts. But certainly that won't be a single line to write, so was the advise to search first in existing Nim libraries.
Re: Partial casing is foo_bar
> Simplify, simplify, simplify Such a language already exists, Basic. But instead of just using that probably it's more fun to choose one of the most feature-rich languages and advertise triple simplicity for it. Then further steps: promote rejecting pointer arithmetic in C and OOP in Java.
Re: My stupid usage of cstrings
Yes, if the strings used are stored somewhere as `string` at the time they are checked, the output is normal, e.g.: var s: seq[string] proc genArray(i, j: int) : seq[cstring] = result = newSeqOfCap[cstring](j - i + 1) s = newSeqOfCap[string](j - i + 1) for k in i .. j: s.add $k result.add((s[k-i]).cstring)
Re: Advent of Nim
Probably it was on moderation. Now it's visible.
Re:
* yes, to make inheritance easier (vars of different types (ancestors, descendants) are of the same size, size of a pointer) * no copying when passing - good for large objects, or when transmitted or used as arguments often * you can use arrays/seqs of different-sized (disregarding inheritance) ref-objects - really arrays of pointers * you can even store them in collections of arbitrary references (of any, incl. non-object, type) or just pointer-sized values And the like, just examples. Ref-objects are allocated on heap, that is they require memory allocation, so when you don't have reasons to use them (in simple cases esp.), better to use value objects, which in Nim are no-overhead (say, a no-inheritance object containing 2 integers is of the size 2 integers, which are located directly in it and are passed to procs on stack).
Re: Error with using concepts
Just define `log(varargs[F])` before `log(Fer)`. From the error messages you see in the body of `log(Fer)` only this one `log` is known, compiler is unaware of the second.
Re: trying to find a language very like nim
Interesting, it has `slurp` with the same meaning, as in Nim.
Re: Big integer litterals
_Stefan_Salewski:_ Your example though compiles, gives wrong result - just of 4 lower bytes. var x: int = 10 * 1_000_000_000 var y: int = 1410065408 echo x # => 1410065408 echo x == y # => true echo x == (10_000_000_000 and 0x_) # => true This should be because of Nim's/C's compiler's 32-bitness.
Re: Estimation of π using Leibniz series
Using exponentiation just for interlacing 1, -1, 1, -1, ... is pointless (apart from mathematical formulas on paper) and should not be done, so no matter if some compiler optimizes it.
Re: Nim and hot loading - any experiences to share?
I get that SIGSEGV instantly, _exit via ctrl + c_ and 1 _version 1_ been printed. I get that immediate SIGSEGV even for empty _main.nim_ and _lib.nim_.
Re: Question about using the "new" built in
[http://nim-lang.org/docs/manual.html#types-object-construction](http://forum.nim-lang.org///nim-lang.org/docs/manual.html#types-object-construction) "For a `ref object` type `system.new` is invoked implicitly."
Re: Are array types that differ only in index boundaries different?
Regarding assignment, it doesn't have to depend on types being indistinguishable. E.g.: proc p(x: int) = echo "int" proc p(x: int8) = echo "int8" var x: int8 x=3 # implicit conversion p x # int8 p 3 # int overloading works here, while allowing literal's assignment with implicit conversion.
Re: `-` operator overloading and negative numbers of distinct type
The overflow is because of an infinite loop (and compiler shows it). Your proc `-` does nothing, except of calling itself with same argument. It doesn't call the `-` of `float32`, as you probably expect - the arguments type is still `F_TYPE`. So just say to compiler to call the `-` of `float32`, by calling it for an `F_TYPE` value: proc `-`*(a:F_TYPE): F_TYPE = return (-a.float32).F_TYPE The same for two other procs. Or you can do simpler - just borrow parent type's procs: proc `-`*(a:F_TYPE): F_TYPE {.borrow.}
Re: What happened to term rewriting macro?
I hope there's no plans of deprecation/removal, docs are where there were, docs/manual/trmacros.txt.
Re: Enum related error: duplicate case value
There's a pragma for setting the size of an enum. Works with `SUBSCRIPTIONS_REQUEST = 0x` if the enum is defined beginning with `EVENT_GROUPS* {.size: sizeof(cint).} = enum ``, and ``var v:EVENT_GROUPS = HANDLE_INITIALIZATION` is uncommented instead of `var v = 0`.
Re: Formatted Backend Output?
nim c --lineDir:on --embedsrc yourProjectFile
Re: My stupid usage of cstrings
or proc genArray(i, j: int) : seq[cstring] = result = newSeqOfCap[cstring](j - i + 1) for k in i .. j: let s = $k GC_ref(s) result.add(s.cstring)
Re: Macros and imports
There should be nothing special for this case, if the macro is used in the same module, where defined. You just need to use `import` before calling the macro (but can use after the macro definition itself). If the proc is defined in one module (_a_), the macro in another (_b_) and is called in yet another (_c_), then you need either: * `import a` in _c_, prior to calling the macro; no need then to import _a_ in _b_, the macro will use an unbound identifier; so you can really then have in the same program some another module (_a2_) defining a proc with same name and imported, together with _b_, in yet another module (_c2_); so, in _c_ a proc from _a_ will be called, and in _c2_ \- from _a2_, both via the same macro from _b_. * you can bind the identifier used in macro (for the proc) to the actual symbol (to the proc from _a_), using `newCall(bindSym"theProcFromA")` instead of `newCall("theProcFromA")` (what Araq suggested), so what imported in _c_ (or where the macro is used) doesn't matter; _a_ should be imported in _b_ then before the macro's definition. * in templates or quote do: in macros by default identifier is bound if the symbol is in scope of the macro definition (i.e. will refer to the same proc), and unbound otherwise; you can force binding (as with `bindSym`) by using `bind` statement (then you'll get a compile-time error, if the proc is not in the scope, instead of late binding), or force letting it unbound by `mixin` statement; in `quote do:` you can also just use backticks around identifiers for explicit binding (you might need to declare the proc with as _procvar_ (say, via `{.procvar.}`) for this to work). E.g.: # module a proc p* = echo "p of a" proc pv* {.procvar.} = echo "pv of a" #module a2 proc p* = echo "p of a2" # module b import a import macros macro x1*: untyped = result = newNimNode(nnkStmtList) result.add newCall(bindSym"p") # the same macro x2*: untyped = result = quote do: bind p p() # yet the same, but ``pv`` should be a ``procvar`` macro x3*: untyped = result = quote do: `pv`() # all ``x1``, ``x2`` and ``x3`` will call ``a.p``/``a.pv``, wherever called # ``p`` is always unbound macro y1*: untyped = result = newNimNode(nnkStmtList) result.add newCall("p") # ``p`` is bound, just because *a* is imported, would be unbound otherwise macro y2*: untyped = result = quote do: p() # ``p`` is implicitly unbound template y3* = mixin p p() # module c # the main module for the example import b x1() # -> p of a x2() # -> p of a x3() # -> p of a import a y1() # -> p of a y2() # -> p of a y3() # -> p of a import c2 # module c2 import b x1() # -> p of a x2() # -> p of a x3() # -> pv of a import a2 y1() # -> p of a2 y2() # -> p of a #y3() # won't compile, both ``p`` from *a* and *a2* match
Re: Traybar support ?
If it's for windows, the API itself is quite simple (maybe it's not hard for other platforms too). There are several gui frameworks available, there may be this functionality available, better check them first. A quick example for WInAPI (`nimble install oldwinapi` to make `windows` available): import windows, os # some missing stuff const NIF_ICON = 0x0002 const NIF_TIP = 0x0004 const NIF_STATE = 0x0008 const NIM_ADD = 0.DWORD const NIM_MODIFY= 1.DWORD const NIM_DELETE= 2.DWORD # a dummy window, to pass its handle to tray icon's creation proc; # use any your program's window instead, and then just skip this piece of code let className = "BUTTON" let windowName = "test" let hw=CreateWindow( className.cstring, windowName.cstring, 0, # dwStyle 400, 300, 200, 60, # position and size 0, # hWndParent 0, # hMenu 0, #hInstance nil) # just filling the structure, describing your icon, and passing it to the API proc; # a callback can be set here too var nid: NotifyIconDataA nid.cbSize = nid.sizeof.DWORD nid.Wnd = hw nid.uFlags = NIF_ICON or NIF_TIP nid.hIcon = LoadIcon(0, IDI_EXCLAMATION) var s = "Hello from WinAPI!" copyMem nid.szTip.addr, s[0].addr, s.len nid.szTip[s.len] = '\0' discard Shell_NotifyIconA(NIM_ADD, addr nid) # here should be your message loop; you have that propbably already; # instead, for a demostration, we just keep the process alive for some seconds, # enough to see icon working, with a hint on it sleep 8_000
Re: Community name?
Because C programmers don't constitute a community (probably did in 1970s), and mostly don't even choose, just happen to program in C, and new languages have not just users, but rather followers, they have to be a bit of a cult to have ones. Well, it is so not only about languages.
Re: Using this over tables?
Of coarse you can use it. But yes, performance will suffer, if you have more than several items in such a table (you iterate through half its length on average). The syntax is described in the manual, and is the usual way to set initial values for hash-tables.