Re: The Philosophies Of Software Languages
> Like I said in another thread, Nim makes trade-offs that benefit developer > writing convenience over the strict consistency and explicitness found in > languages like Ada, Java, Go, and even Python. Yeah you said that, and I think it's quite wrong. There is no trade-off between readability and ease-of-writing in the classical sense; maybe Perl does that, but Nim doesn't. The difference between t[x] = t[y] + 1 Run and tables.put(t, x, system.`+`(tables.get(t, y), 1)) Run is not clear cut. It's much easier to spot the bug in the first variant (it should have been `t[x] = t[x] + 1`)... I prefer to see the _algorithms_ not the plumbing. If the `[]=` operator doesn't do what I think it does, it's misnamed -- no matter the module it's coming from. Furthermore, a world where `x.len` is different from `x.len()` which is different from `len(x)` is not adding clarity at all, it's even more confusing -- what's the difference between them? Do I need to watch out to call the right one? Is one slower than the other?
Re: Not-so-distinct types
If all you want is to prevent the equality operator (==), you can do: type I1 = distinct uint32 I2 = distinct uint32 converter toU32 (value: I1): uint32 = value.uint32 converter toU32 (value: I2): uint32 = value.uint32 proc `==`(i1: I1, i2: I2): bool {.error: "Thou shall not compare types I1 and I2".} var v: uint32 = 1 v1: I1 = 1.I1 v2: I2 = 1.I2 if (v1 == v): # works echo "1: true" if (v2 == v): # works echo "2: true" if (v1 == v2): # compile error! echo "3: true" Run
Re: Not-so-distinct types
I looked into converters, which I didn't know about. I thought the following might work: make all the type distinct, but automatic conversion to uint32 to remove the 'distinction' between sub-type and base type. type I1 = distinct uint32 I2 = distinct uint32 converter toU32 (value: I1): uint32 = result = value.uint32 converter toI32 (value: I1): int32 = result = value.int32 converter toU32 (value: I2): uint32 = result = value.uint32 converter toI32 (value: I2): int32 = result = value.int32 var v: uint32 = 1 v1: I1 = 1.I1 v2: I2 = 1.I2 if (v1 == v): echo "1: true" if (v2 == v): echo "2: true" if (v1 == v2): echo "3: true" Run Returns 3 trues. Still no cigar...
The Philosophies Of Software Languages
There's a recently-concluded series of four articles collectively titled " **The Philosophies Of Software Languages** " : * Foundations, 1940 to 1972, [From Plankalkül to C](https://www.welcometothejungle.co/fr/articles/philosophies-software-languages) (includes Fortran, Cobol, Algol, Simula, BCPL/C) * Revolution, 1972 to 1991, [From Smalltalk to Perl](https://www.welcometothejungle.co/fr/articles/philosophies-programming-languages) (includes C++, ObjC, Haskell) * Evolution, 1991 to 2000, [From Java to JavaScript](https://www.welcometothejungle.co/fr/articles/philosophies-software-languages-javascript) (includes Python and Ruby) * Divergence, 2000 to _now_ , [From Go to Elixir](https://www.welcometothejungle.co/fr/articles/languages-software-go-elixir)" (includes Rust and Kotlin) It's understandable that it doesn't mention Nim, because its popularity metrics are still far below those languages, although they are growing quickly. Of course any such analysis is an over-simplification. There aren't distinct eras and many different trends happening at once. But it's still a worthy topic of discussion. It's interesting to speculate how Nim can fit into that narrative if/when it gains popularity several years from now, and how the next major "era" of programming language design can be surmised. Some ideas: * **Ubiquity of tooling.** Like I said [in another thread](https://forum.nim-lang.org/t/4770#29838), Nim makes trade-offs that benefit developer writing convenience over the strict consistency and explicitness found in languages like Ada, Java, Go, and even Python. Human beings write code. Computers read code. Computer time is _much_ cheaper. Computers can then reformat the code to be as explicit and readable as desired. The IDE (or a Web code view widget) can give you all the insight into the code that the most explicit language can give, but without cluttering you with obvious bureaucratic red tape when you don't want it. The ability to read code on dead tree pulp is no longer a priority. * **Ubiquity of execution.** Make an app that can run in several modes with a single codebase: do most of the work on the Web server, or run serverless inside the Web browser (ex. IPFS, WebAssembly), or in a desktop app, or a mobile app (ex. [nimx](https://github.com/yglukhov/nimx)), etc. Languages like Kotlin and Haxe can target more VMs directly, but Nim is definitely a contender, and smaller binary sizes than Rust could make it a better choice for WebAssembly. * **Ubiquity of DSLs**... (I might add more ideas later.)
Re: OpenWL/DL - two foundation libraries for building a cross-platform GUI with non-C++ languages
Note the menu aspect of my minimal example above isn't necessary - I just find it super convenient to have when testing so I'm never without a keyboard shortcut for exiting.
Re: OpenWL/DL - two foundation libraries for building a cross-platform GUI with non-C++ languages
So here's a minimal Mac example, current as of right now: [https://gist.github.com/dewf/d1de81fb9bbc7f1cd82d389f94f0e7e2](https://gist.github.com/dewf/d1de81fb9bbc7f1cd82d389f94f0e7e2) Bad news, though - I just pushed a [mass API rename](https://github.com/dewf/openwl/commit/9e7fb334124e9667d99489ba33eece5e0dbd9a8e) on OpenWL this morning. The example you're showing above is a mixture of old and new naming convention, so perhaps that has something to do with the segfaults? (Sorry, it needed to be done, and sooner than later! Now it's consistent with OpenDL naming, and I'm much happier with it) By the way, how are you linking / running this? Mac is a bit weird because (AFAIK) the GUI executables need to sit in a bundle with a .plist that describes the app a bit, otherwise it won't work quite right. So what I usually end up doing is building a dummy desktop Cocoa app in Xcode, and then using the app bundle it creates as a skeleton. And then there's the misery of getting .dylibs properly found by executables... but since you're getting this far (crashing on wl_WindowShow) then I guess you're past all that.
Re: OpenWL/DL - two foundation libraries for building a cross-platform GUI with non-C++ languages
I use MinGW with nim on windows all the time. I have never heard of winpty or MSYS2. To get rid of the console for a windows app from nim we just pass \--app:gui not sure what you need to do in C++ to do that. I manage to get some of OpenWL working on Mac with the help of @shashlick's modified script (here: [https://gist.github.com/treeform/47865e7d06694fc224f0c492cdee41d3](https://gist.github.com/treeform/47865e7d06694fc224f0c492cdee41d3) ) import openwl echo wl_GetPlatform() proc eventLoop(window: wlWindow; event: ptr WLEvent; userData: pointer): cint {.cdecl.} = echo "here" var opts = WLPlatformOptions() discard wl_Init(eventLoop, addr opts) var props = WLWindowProperties() props.usedFields = ord(WLWindowProp_MinWidth) or ord(WLWindowProp_MinHeight) or ord(WLWindowProp_MaxWidth) or ord(WLWindowProp_MaxHeight) props.minWidth = 300 props.minHeight = 200 props.maxWidth = 1600 props.maxHeight = 900 let width = 800 height = 600 var mainWindow = wl_WindowCreate(cint width, cint height, "hello there, cross-platform friend āǢʥϢ۩ใ ♥☺☼", nil, addr props) wl_WindowShow(mainWindow) # <-- segfaults discard wl_Runloop() Run I am getting SIGSEGV when trying to show the window. Is there anything extra I need to do to the window to make it showable? Like add a menu or do any of the things in platformInit? Do you have a super minimal openWL example?
Can we suppress =destroy call for a local var?
Replacing finalizers with destructors for gintro seems to work in principle, at least I got cairo_anim.nim running with a few hacks. Problem is similar as with finalizers -- for callback vars owned by gtk we do not want a finalizer or destroy call, while for ordinary use we want the call. For finalizers I made the var global to prevent finalizer call. But for destroy global pragma makes no difference. What I have is basically type Context00* = object Context* = object of RootObj impl*: ptr Context00 proc `=destroy`*(s: var Context) = echo "=destroy called" if s.impl != nil: cairo_destroy(s.impl) s.impl = nil proc `=sink`*(s: var Context; x: Context) = echo "=sink called" if s.impl != nil and s.impl != x.impl: cairo_destroy(s.impl) s.impl = nil s.impl = x.impl Run and the macro generated callback proc proc connect_for_signal_cdecl_draw1(self: ptr Widget00; cr: ptr cairo.Context00; data: pointer): gboolean {.cdecl.} = let h: pointer = g_object_get_qdata(self, Quark) var cr1: cairo.Context cr1.impl = cr drawingAreaDrawCb(cast[DrawingArea](h), cr1).ord.gboolean Run (Here drawingAreaDrawCb() is the user provided high level callback proc.) Unfortunately at the end of connect proc =destroy is called for cr1, resulting in freeing cr which is owned by gtk. I tried sink and lent modifier for cr1, but that does not work, at least not in macro. So there remain two solutions: 1: cr1.impl = nil at end of connect proc, so destroy is called but does nothing. 2: Use ContextXX* = object of Context for type of cr1, that prevents call of =destroy currently, but I am not sure if that is guaranteed.
Re: Example implementing SQLite extension in Nim
I've been testing this with a similar setup to yours, but maybe we have different options for the SQLite library we're testing against. The default SQLite install on my Mac didn't have loadable extension support compiled in, so I tested with a separate SQLite amalgamation. Its the same version of SQLite that you were testing with. I'm presuming that you took the default options to 'configure' when you built your SQLite, but if not let me know.
Re: Not-so-distinct types
If the mapping is fixed, you can use [subrange](https://nim-lang.org/docs/manual.html#types-subrange-types) types. Although the base type is same, you can define like type Row1 = range[ 0 .. 71 ] # assuming row has 72 bytes Row2 = range[ 72 .. 143 ] Run Maybe like that?
Re: Not-so-distinct types
As you guessed, the content of the memory map will be variants. The memory will contain uint32 from time to time. But it will also be int32, float32, addresses, and other things. The hardware I am looking at emulating is the OpenGenera lisp machine where memory content was tagged. So it seems that what I was looking for is not possible in Nim (not that I had any expectations in Nim or any other language). Thanks to all for taking the time to answer.
Re: Not-so-distinct types
Is [distinct](https://nim-lang.org/docs/manual.html#types-distinct-type) not what you need? You can define the needed operations from its base type using `borrow` pragma so you don't have to cast/coerce every time you use it Also, I did what @cdome suggested, defining `converter` s and it works like charm. I have several subtype and using converters to convert back and forth between the base type and its subtype.
Re: Not-so-distinct types
I guess that will not work: When your "memory map" is just a plain array of uint32 types, then all entries are equal. That is because in Nim by design all elements of an array have the same type, and more importantly, unit32 is just 32 bit, which is used all for storing numbers, there is no bit free to encode type. In Nim you may use objects of different type, maybe object variants, or refs to various object, which you can store inside an array. But that will consume additional memory. Or you may decide to just use a few bits of your uint32 to indicate type, and remaining bits for the numbers. That is a low level hack. You may know the keyword distinct, it can be used to create distinct types. But I think it does not help you, as an array can only contain one single type.
Re: Will an object instance passed to a proc not generate a =destroy call?
Maybe now I understand: Proc parameters are unmutable in Nim, so there is no reason to destroy the copy. Only when inside the proc we have var myVal = myprocPar then we get a new mutable instance, which is destroyed. And my feeling is that = proc is never used for passing parameters to procs, but only for direct assignment.
Re: Not-so-distinct types
Maybe some background will help. To learn Nim, I decided to write an emulator. Obviously an over-ambitious project that will never be finished, but nevertheless seems to me a good use for Nim (if only judging by the Nimes emulator). I want to index the memory map by a 'memory address' type. That would be a uint32. Obviously, some memory content would also be uint32 (as a value) for time to time, or an address (pointer) from time to time. I want the type system to keep me on my toes (no mixing of addresses and values), but I want it out of the way when using addresses as an index in the array representing the memory.
Re: Not-so-distinct types
> All true or all false is not what I am looking for though. Do you want to compare types or values? You can compare values only, when the types are compatible, that is when types are equal or when there is a converter. In your initial post you compared values, that worked because your types were only aliases. But I guess you may want to compare the types?
Re: Not-so-distinct types
Correct. I get the equivalent (if I am not wrong this time) of Haskell's newtype declaration. I am looking for an half-way street. The benefit of static typing without the hard work of casting/coercion Basically I want the compiler to do everything for me without being a pain when I don't want it to I tried using 'template' to declare the v1 and v2 declaration but that didn't achieve what I want too. I appreciate I am asking for something unusual, at least in the sense I have not seen that in any other language I know. If it is not possible in Nim, no worries.
Re: Not-so-distinct types
I apologise. You are right. I completely inverted the results. They are all true. All true or all false is not what I am looking for though.
Re: Will an object instance passed to a proc not generate a =destroy call?
I can rewrite it this way: O {.bycopy.} = object i: int proc new(o: var O) = echo "new called" proc `=destroy`*(s: var O) = echo "=destroy called" proc `=sink`*(a: var O; b: O) = echo "=sink called" a.i = b.i proc createO: O = result.i = 7 proc p(o: sink O) = echo "working with o" echo o.i proc main = var o: O = createO() p(o) echo o.i main() nim Run $ ./h =sink called working with o 7 7 =destroy called Run So p() has a sink parameter. But should not the echo after call of p() force a copy, so that we get two destroys?
Will an object instance passed to a proc not generate a =destroy call?
I was just thinking about how I can prevent a call of destroy from within a proc, because for callbacks we do not want destroy calls for parameters owned by GTK. But it seems that this tests does not generate a destroy call for proc parameter at all? type O {.bycopy.} = object i: int proc new(o: var O) = echo "new called" proc `=destroy`*(s: var O) = echo "=destroy called" proc `=sink`*(a: var O; b: O) = echo "=sink called" proc createO: O = result.i = 7 proc p(o: O) = echo "working with o" echo o.i proc main = var o: O = createO() p(o) echo o.i main() Run $ ./h =sink called working with o 0 0 =destroy called Run I have added the bycopy pragma, but that makes no difference. There is only one destroy call, and that is for the o var in main. When I add a local var of type O to proc p() we get another destroy call as expected.
Re: HttpClient "Name or service not known"
Here's a way to replicate the bug: 1. Install mitmproxy and run it 2. Install the generated mitmproxy .pem file onto your machine 3. export http_proxy=http://127.0.0.1:8080 and export https_proxy=http://127.0.0.1:8080 4. Run curl https://forum.nim-lang.org/ outputs the html correctly 5\. Run nim c -d:ssl -r test.nim raises error shown above
Re: HttpClient "Name or service not known"
I see. connectionUrl.hostname has something when you echo it the object but not when you echo the field itself, try using repr, it's possible that there is a 0 (end-of-string) character in that string.
Re: HttpClient "Name or service not known"
@dom96 I'd like to fix it but in one of my previous comments I presented something that shouldn't happen. If someone has a clue about that issue then I will be able to continue but otherwise I'm in the dark.
Re: Example implementing SQLite extension in Nim
yeah: sqlite> .load libhello_world.dylib Traceback (most recent call last) functions.nim(141) sqlite3_helloworld_init SIGSEGV: Illegal storage access. (Attempt to read from nil?) Run
Re: Is allowing non-matching types for assignment overloading in the development timeline?
By the way, to restrict conversion to literals you can use the {lit} constraint converter toIntAp(n: int{lit}): IntAp Run Otherwise some subtle bugs might be introduced where you or your user do not want because an int was converted silently to IntAp.
Re: Is allowing non-matching types for assignment overloading in the development timeline?
Wow thanks, I didn't know about this use of converters. I can simplify a lot it code with this!
Re: Not-so-distinct types
Might work, untested idea: Define convertors from t1 to base and t2 to base
Re: HttpClient "Name or service not known"
It happens because either: 1\. You are doing something wrong, like not setting the http_proxy env var (Unlikely since it works for you in curl) 2\. There is a bug in the httpclient module (Likely as there were other bugs with the proxy support before) I don't use proxies, I also don't have the time to look into every single issue that pops up. So it would be really helpful if you could try to fix this. Nim is an open source project and we don't have many resources (building a language is hard), so the only way we can scale is if everyone that uses Nim and finds bugs does their best to fix them. If you're getting stuck finding the cause of this then please join our IRC/Gitter where someone will give you hand: [https://nim-lang.org/community.html](https://nim-lang.org/community.html).
Re: Not-so-distinct types
Type1 and Type2 are not distinct types, they are just aliases. You are declaring a different name for the same type uint32, there is no subtyping here
Re: HttpClient "Name or service not known"
Why does this happen? Can we ever expect proper proxy support for nim? Because if we can't then I might as well just change language or use curl as a replacement.
Re: Not-so-distinct types
I get true for both: var v:uint32 = 1 type Type1 = uint32 var v1: Type1 = 1 type Type2 = uint32 var v2: Type2 = 1 echo(v1 == v2) echo(v == v1) Run nim 0.19.4