Nimsuggest and Manjaro Nim installation

2024-06-10 Thread lscrd
The problem has been solved.

Thanks to the team for the correction.


Nimsuggest and Manjaro Nim installation

2024-06-07 Thread lscrd
Looking again at your answer, it seems obvious.

It looks like I was not wide-awake at this moment. My apologies.


Nimsuggest and Manjaro Nim installation

2024-06-07 Thread lscrd
I guess this is supposed to be ironic.

Contrary to what you said, the compiler and _nimsuggest_ doesn’t use the same 
rule. I have no time to find the reason for this, but one thing is sure: if 
_nim_ binary is in /usr/bin, the compiler does the right thing and expects the 
library to be in /usr/lib/nim while _nimsuggest_ expects it to be in /usr/lib.

When I have time, I will create an issue for this. At least, I expect that 
someone will check and give me a better answer that yours.


Nimsuggest and Manjaro Nim installation

2024-06-07 Thread lscrd
You are right. If the compiler used the same logic as that of _nimsuggest_ to 
find the library location, it should not work. This is strange.

To understand what going on, I looked at the compiler source. In the module 
“options.nim” of the compiler, the procedure _getPrefixDir_ has a special case 
for Posix platform. If the parent is /usr, then the prefix directory is set to 
usr/lib/nim.

For some reason, _nimsuggest_ doesn’t call _getPrefixDir_ but uses a simplified 
rule. And, so, the library path is set to /usr/lib which is wrong. Now, there 
may be a good reason to not use _getPrefixDir_ in _nimsuggest.nim_.

So there should be no problem to install Nim on Linux in the standard locations 
since the case has been foreseen . But, actually, there is a problem with 
_nimsuggest_. 


Nimsuggest and Manjaro Nim installation

2024-06-07 Thread lscrd
Thanks for your detailed answer. It makes sense.


Nimsuggest and Manjaro Nim installation

2024-06-06 Thread lscrd
I tried to use Nim standard installation on Manjaro and encountered a problem 
with _nimsuggest_. When running _nimsuggest --v3_ , I get an exception with the 
message _cannot open '/usr/lib/system.nim'_.

Manjaro installs Nim binary in /usr/bin and the library in /usr/lib/nim. 
Looking at the source, it appears that _nimsuggest_ looks for a directory named 
“lib” in the parent directory of /usr/bin and, of course, finds /usr/lib. Then 
it expects the library files to be present here, not in a subdirectory.

Should we consider that Manjaro installation of Nim is broken since it doesn’t 
follow this requirement or that there is a problem with the way _nimsuggest_ 
searches the standard library location?

In the first case, how the Manjaro installer should proceed? Installing the 
binary in /usr/bin is standard and installing the library files in a 
subdirectory of /usr/lib seems the right thing to do.

Of course, there are other ways to install Nim, but it is reasonable to expect 
a distribution to provide a standard way to install the compiler and the tools 
as it is the case for other languages.


`nph` opinonated formatter v0.2

2023-12-27 Thread lscrd
Sorry, I should have taken a better look at the previous posts 🙁.

For me, it looks like a bug in the parser. As you said, it seems that the 
parser has swallowed the semicolon when processing the inner proc.

Using a modified example with only standard types, I found two workarounds: 
either add an extra semicolon to terminate the inner proc definition or put the 
whole inner proc definition between parentheses. In both cases, this helps the 
parser to understand that the definition is terminated.

Of course, these are only workarounds.

Regarding `nph`, we have indeed been warned: it is opinionated, so I understand 
that it is impossible to satisfy everybody. But, anyway, I think that style 
debate is inevitable for a code formatter 🙂.


`nph` opinonated formatter v0.2

2023-12-27 Thread lscrd
Sorry, I don’t understand why using `;` is not possible for identifiers with 
defaults. The following example is perfectly valid and I don’t see any parsing 
problem:


proc p(a: int; b: char; c, d = 3; e = 4) = discard


Run

Am I missing something? Is there any problem with the AST in this case?

As regards consistency, I don’t see why we should use the same separator for 
parameters in function/procedure definitions and in function/procedure calls, 
since a parameter list in a procedure definition is syntactically totally 
different of a parameter list in a procedure call.

In fact, Nim is not the first language to encounter this problem. Several 
languages use semicolons as separator in procedure definition, for instance 
Pascal, Modula family, Ada.

If people tends to use colons rather than semicolons, this is not because this 
is more rational or more consistent but rather that many people have practiced 
languages such as C, C++, Python, Ruby, etc., which use a comma as separator. 
However, as Nim's syntax is closer to that of languages such as Pascal 
(particularly in the definition of parameters), I think that the semicolon 
makes more sense.

It's not that I'm advocating replacing commas with semicolons, but as the 
semicolon is more rational and more legible, I think it's only fair to respect 
the choice of those who have adopted it.


Hello `nph`, an opinionated source code formatter for Nim

2023-12-11 Thread lscrd
Personally, I systematically use `;` in parameter list as this is more readable 
than `,` when successive parameters have the same type.


proc p(x, y: int, c: char)

Run

seems to me confusing compared to


proc p(x, y: int; c: char)

Run


Advent of Nim 2023

2023-12-02 Thread lscrd
My solutions, all written in Nim, can be found here:

<https://github.com/lscrd/AdventOfCode2023>

Solutions for years 2016 to 2022 can also be found on 
<https://github.com/lscrd>.


A few (perhaps naive) questions

2023-08-08 Thread lscrd
Yes, but until the links are changed you have to specify the URL:


nimble install https://github.com/adokitkat/nim-gmp
nimble install https://github.com/adokitkat/bignum


Run

Don’t forget to remove the old versions.


A few (perhaps naive) questions

2023-08-08 Thread lscrd
Thank you! Great work!


A few (perhaps naive) questions

2023-08-07 Thread lscrd
“bignum” no longer works. There is a syntactical error in the “gmp” wrapper 
used by “bignum”. For some reason, it worked with 1.6, but 2.0 is less 
permissive regarding the position of pragmas.

The issue has been reported since December (for Nim 2.0 RC). But you know it as 
you have just added a comment regarding this issue here: 


This is a pity as “bignum” is the most complete big integers library as it 
includes also big rationals. And is faster than “bigint”.

There is also “integers” which proposes a better API than “bignum” (but without 
rationals). As it uses its own wrapper to GMP, it works with Nim 2.0: 



“NIM” backronyms

2023-05-23 Thread lscrd
Not in my… Nim!


Checking for exact floating-point representations

2023-05-01 Thread lscrd
You are right. For instance 0.6 cannot be represented exactly as a binary float.


Type mismatch with echo and trouble accessing Type fields

2023-04-19 Thread lscrd
If you do this, you will encounter problems if your ref type contains fields 
which are also references. At what depth will you stop? And, worse, if there 
are cycles, you will enter in an infinite recursion.


Advent of Nim 2022

2022-12-11 Thread lscrd
I suppose that the bug will be fixed in 1.6.12 version but I don’t know when 
this version will be released.


Advent of Nim 2022

2022-12-06 Thread lscrd
My solutions are available here:

<https://github.com/lscrd/AdventOfCode2022>

When solving day 06, I encountered a bug in Nim 1.6.10 "strutils" library. In 
"s.find(sub, start, last)", if "last" is equal to 0, this is interpreted as 
"s.high" which is wrong.

This bug has been fixed in the development version (using -1 as special index 
value instead of 0). I reported an issue, only to take track of the problem, 
but, of course, it is now closed.


Nim Compiler Issues

2022-09-10 Thread lscrd
It seems that you want to define arras containing values of different types. 
This is not possible in Nim and it doesn’t matter if the type is already known 
(predefined) or not.

When you use the union operator `or` to define the type “byte”, it means that 
you can define a common behavior for variables, constants, parameters of type 
`range[uint8(0)..uint8(128)]`, `range[0x00..0x80]` or `char`. It doesn’t mean 
that you can mix values of these types, either when assigning them, comparing 
them or grouping them in an array.

And when using a value of “abstract” type “byte”, you have to make sure that 
its actual concrete type is known at compile time. You can write generic code 
using “byte”, but anyway, values must finally be of a concrete type with the 
restrictions enforced by a statically and strongly typed language.

I don’t use concepts, but this is only a way to raise the level of abstraction 
and they don’t allow to override the fundamental constraint regarding value 
types.

To avoid the explicit conversions, you could use converters, but I don’t know 
how they behave when defining values in an array.

And to conclude, the Nim way to mix values of different types consists to use 
object variants. But it seems a bit overkill in this case.


Nim Compiler Issues

2022-09-09 Thread lscrd
I don’t see how this program can compile.

Here is a version which compiles:


# worked
type byte = range[uint8(0)..uint8(128)]  # or just uint8 without the range
type bytearray[H: static uint64] = array[uint64(0)..H, byte]

const b = byte('a')
const ba: bytearray[1] = [byte(0x80), b]


Run

First, when defining “b” you need to convert 'a' to a “byte” as you explained 
in your comment.

Then, when defining “ba” you need to convert 0x80 to a “byte” in the array 
literal. If you don’t specify that the first value is a “byte”, then the array 
is expected to contain values of the same type as the first one, which is of 
type “int”. As the second value is of type “byte", there is a mismatch.


How to have multiple (alternate) return types?

2022-09-02 Thread lscrd
But this is a valid return type, provided the actual return type is known at 
compile time.

This is valid and the result is what you expect:


proc test(x: static bool): string | int =
  when x:
1
  else:
"hello"

echo test true
echo test false


Run


Can if statements be used as expressions everywhere?

2022-02-12 Thread lscrd
Yes, but, nevertheless, in this case, you have to use parentheses. This is the 
same thing with an if expression:


proc p(b: bool) =
  var x = if b: 3 else: 4 # Compile.
  var y = 1 + if b: 3 else: 4 # Doesn’t compile.
  var z = 1 + (if b: 3 else: 4)   # Compile.


Run

Maybe this is a bug, but I don’t think so. This is probably a parsing 
constraint.


Can if statements be used as expressions everywhere?

2022-02-12 Thread lscrd
You need to use parentheses to turn the case statement into an expression:


import std/strutils

func score*(word: string): int =
  for c in word:
result += (case toUpperAscii(c)
  of {'A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T'}: 1
  of {'D', 'G'}: 2
  of {'B', 'C', 'M', 'P'}: 3
  of {'F', 'H', 'V', 'W', 'Y'}: 4
  of 'K': 5
  of {'J', 'X'}: 8
  of {'Q', 'Z'}: 10
  else: 0)


Run


Trojan:Win32/Wacatac.B!ml

2022-01-24 Thread lscrd
> Exactly, it's not an easy task. Why not just submit a false positive report?

It was already done for previous versions of Nim. Perhaps it would be possible 
to take out a subscription because things don't seem likely to change anytime 
soon 🙂.


Trojan:Win32/Wacatac.B!ml

2022-01-23 Thread lscrd
Yes, it may happen. I once encountered this problem when installing one of our 
programs on a customer computer. Fortunately, the antivirus software had not 
been updated for some time and after update the false positive disappeared.

In fact, I suppose it happens of lot of time, but nobody cares except when the 
victim is a well known software.

Malware detection is not an easy task and there is no way to avoid some false 
positives, but we should expect that when a problem has been encountered, 
actions will be taken to avoid the same problem to occur again and again.

So, if Windows Defender hit Chrome in the past, I’m pretty sure that it will 
not happen again. But, since Nim has been used to write malware, each version 
of Nim is hurt by antivirus software. It’s clear that Microsoft and others 
simply don’t care. 


Trojan:Win32/Wacatac.B!ml

2022-01-23 Thread lscrd
This isn’t the job of developers to provide binaries to Microsoft (and all 
other virus software providers) each time they release a new version. It’s the 
job of antivirus software developers to make sure they provide correct 
signatures for malware detection.

A false positive may occur, but when it occurs each time a new version of some 
software is released, that means that the signatures are not precise enough and 
must be refined.

Microsoft has already been warned that Window Defender creates false positives 
for programs written in Nim. So, it knows that its signatures are too coarse. 
But, obviously, nothing has been done.

We don’t hear that each time a new version of gcc is produced, there are a lot 
of false positives with program written in C. Of course, Microsoft (and others) 
are very careful to create signatures which detect the wrong and significant 
part in malware code written in C.

It’s clear that for malware written in Nim, they have been able to catch a 
common pattern but, unfortunately, this common pattern is strongly correlated 
to Nim and not much to the malware part.


Trojan:Win32/Wacatac.B!ml

2022-01-23 Thread lscrd
Apparently, this doesn’t work well as the problem is encountered with each new 
version of Nim. When you have signaled the problem a first time, then a second 
time, etc. it should be evident for the antivirus software maker that it should 
be careful and check that its product doesn’t falsely detect Nim compiler, Nim 
tools and more generally most programs written in Nim as malware.

Clearly, this is too much to expect from some antivirus software providers.

Maybe a solution would be to maintain a list of antivirus software with an 
indication of its behavior regarding programs written in Nim. This way, those 
which are correctly tested would be recommended and the poor ones, such as 
Windows defender, would be flagged as to be avoided.


Novice Question: Implement the Step functionality in VBA

2022-01-14 Thread lscrd
Equivalent to your solution, but more concise:


iterator mystep(a, b: int): int =
  for i in countup(a, b):
yield i
  for i in countdown(a, b + 1):
yield i


Run


Advent of Nim 2021

2021-12-05 Thread lscrd
My repository is here: <https://github.com/lscrd/AdventOfCode2021>


Nim 1.6.0 GTK cast cstring ?

2021-10-21 Thread lscrd
No, there is an implicit conversion when passing a `string` to a `cstring`. But 
it seems that nim 1.6.0 has introduced a check to make sure that the argument 
cannot be modified.

This triggers the warning:


proc p(s: cstring) =
  discard

var s = "abc"
p(s)


Run

and this doesn’t trigger the warning:


proc p(s: cstring) =
  discard

let s = "abc"
p(s)


Run

When the argument is the result of a function call which returns a value (not a 
var), I think that the warning is incorrect.


Question about algorithm.upperBound

2021-10-06 Thread lscrd
Yes, this is a known documentation error which has been fixed in the 
development version. Here is the doc for the function in this version:

> Returns the index of the first element in `a` that is greater than `key`, or 
> last if no such element is found.


Question about "minExponent" and "maxExponent" in module "fenv"

2021-09-24 Thread lscrd
Hi all,

For a float32, we get -125 for minExponent and 128 for maxExponent. It’s a bit 
surprising as the whole range fo exponents is -127..128, so we would expect 
minExponent to be -127. If we limit to normal numbers, the whole range is 
-126..127.

For a float64, we get -1021 and 1024 when we would expect -1023 and 1024 or 
-1022 and 1023 if we limit to normal numbers.

So, I suppose that the meaning of minExponent is not what I expected. Could 
someone explain its meaning?


Print why assert failed?

2021-08-14 Thread lscrd
You may put anything in the message, for instance the value of the arguments:


import strformat

let a = 1
let b = 2

assert a == b, &"Expected {b}, got {a}"

Run

Of course, displaying the arguments by default would be an improvement but, 
most of the time, only the user knows what is the relevant information to 
display.


Print why assert failed?

2021-08-14 Thread lscrd
It is possible to add a message to `assert`:


let a = 1
let b = 2

assert a == b, "Something didn't work."

Run

And we get:


Error: unhandled exception: /tmp/test.nim(4, 8) `a == b` Something didn't 
work. [AssertionDefect]

Run


Nim earns mention in the news (unfortunately?)

2021-07-29 Thread lscrd
Sure. In any domain, the worst thing is to be totally ignored.


How can I point to (the memory adress of) a variable?

2021-07-20 Thread lscrd
> I've read the first part of the tutorial but I found that it needs 
> improvement so here I am asking.

In a tutorial which is intended to learn the basics of the language, there is 
no need to describe unsafe features.

If you want to use there features, you have a lot to learn before. Nim is not C 
and it is possible to do a lot of things using only safe features. Look at 
Rosetta tasks and you will see that `addr` is almost never used, except when 
interfacing with C as @ynfle said.


Safe `enum` conversion

2021-07-05 Thread lscrd
I think that regarding the possibility to catch defects, we are in a 
transitional state. By default, defects are catchable but this will change in 
the future. Personally, I never rely on the possibility to catch defects. That 
means that if I want to check for overflow, I don’t try to do the operation and 
catch the exception, but I do some inefficient tests to prevent the overflow. I 
find this ugly but, at least, there is a good reason to use a defect here: it 
is more efficient.

In other cases, doing a check before doing the operation is not a problem, for 
instance before dividing an integer or before indexing, because the check is 
easy to write and implied by the logic of the program. If the divisor may be 
zero or the index out of range without this being an error, it is normal to 
check these cases.

As regards the conversion to enums, I don’t think that making them raise a 
catchable exception rather than a defect will be such a breaking change. The 
breaking change has already be done been when exceptions have been split in two 
categories using a different mechanism. Switching wouldn’t break a lot of 
thing. And, as I said, parseEnum already raises a ValueError not a RangeDefect.


Safe `enum` conversion

2021-07-04 Thread lscrd
The problem with:


type X = enum
  Z

var a = 42
var b = X(a)


Run

is that it raises a RangeDefect exception and that defects are considered non 
catchable (in fact, by default, they are, for now…).

The distinction between catchable exceptions and defects have been introduced 
because some errors, as division by zero, are really non catchable. But there 
are few of them.

For most defects, this has been a design choice. For instance, we could 
consider an index out of range as a catchable error rather than a defect. I 
don’t say we should, however.

I think that with this conversion, we are in a situation where we could 
consider the error to be catchable. Rather than raising a RangeDefect, the 
compiler could generate code to raise a ValueError. This is what is done by 
parseEnum.

Of course, one can says that it would be inconsistent with the behavior of 
other conversions. That’s true but for other conversions it is easy to make 
sure that they are possible before actually doing the conversion. This is not 
the case for enums, at least when their values are not contiguous.

Another way to keep a consistent behavior should be to change RangeDefect to 
Range Error, i.e. to make the exception catchable.

All other solutions consist to try to do manually the check the compiler does, 
which is fine except for non contiguous enums.


An efficient deque -> array proc to enable index access to all internal values?

2021-06-30 Thread lscrd
Maybe I didn’t understand your question but with Nim deques there is no need to 
use an array proc to access an element. You can do it directly. Here is an 
example of what can be done with Nim deques:


import deques

var d = [1, 3, 5, 7].toDeque

echo d
d.addFirst 0
echo d
d.addLast 8
echo d
echo d[3]
d[2] = 9
echo d
echo d.popFirst
echo d.popLast
echo d
d.shrink(1, 1)
echo d


Run


Formatting a float to currency

2021-06-27 Thread lscrd
`insertSep` from module `strutils` is able to insert separators, but it doesn’t 
work well with floats:


import strutils
echo ($12345.67).insertSep(',')# 12,345,.67.


Run

So we have to do some work to get the right result:


import strutils
var s = ($12345.67).split('.')
s[0] = s[0].insertSep(',')
echo s.join(".")# 12,345.67


Run

It’s not very satisfying, but it avoids to write a lot of code.


import unsigned error

2021-06-20 Thread lscrd
"unsigned" is an old module which has been deprecated and no longer exists.

I’m surprised by this error as I have "bignum" installed on my machine and 
didn’t encounter any problem.

The last version of "bignum" is 1.0.4, yours seems to be 1.0.0, so the problem 
may be just to install the most recent version. But, strangely, on github the 
first line in "int.nim" is "import unsigned" which is indeed wrong. This error 
doesn’t exist in the version I installed using "nimble", so I think you should 
install it this way by typing `nimble install bignum`.

Anyway, there is something not clear in the github version.

Note that it may be enough to delete the faulty import to solve the problem.


lowerBound and upperBoud from module “algorithm”

2021-06-13 Thread lscrd
You are right. I checked and this is the reason why I asked the question here. 
Release 1.4.8 is recent, so I was surprised that it exists a difference with 
the development version.

To better understand, I checked and found that the commit has been done on 
January 2. So, I suppose that the documentation will be updated in next major 
version, but is not updated in minor ones.


lowerBound and upperBoud from module “algorithm”

2021-06-12 Thread lscrd
Thanks. So, it was found before and correction is in the pipe. Fine!


lowerBound and upperBoud from module “algorithm”

2021-06-12 Thread lscrd
When trying to use these functions I got a behavior not consistent with the 
documentation. Here is an example:


import algorithm

let a = [2, 4, 6, 8]

echo a.lowerBound(4)  # display 1
echo a.upperBound(4)  # display 2


Run

The documentation for`lowerbound` in version 1.4.8 says: “Returns a position to 
the first element in the `a` that is greater than `key`, or last if no such 
element is found.” That means that, if all elements are distinct, the value at 
the returned position cannot be equal to the key. If documentation was right, 
we would expect to get 2 instead on 1.

Similarly, the documentation for`upperbound` in version 1.4.8 says: “Returns a 
position to the first element in the `a` that is not less (i.e. greater or 
equal to) than `key`, or last if no such element is found.” If documentation 
was right, in the example we would expect to get 1 instead on 2.

Obviously, the descriptions have been swapped as we expect `lowerBound` to 
return an index less or equal to the one returned by `upperBound`, not the 
reverse.

Now, looking at the issues on github, it appears that the documentations have 
indeed been swapped, but I don’t know if it was a mistake or the correction of 
a mistake. In the documentation of development version, the descriptions seem 
to be right.

I didn’t want to create a new issue before understanding what is the current 
situation. Documentation in version 1.4.8 is wrong, but can we expect that it 
will be right in next version?


high(Natural) == high(int)

2021-06-02 Thread lscrd
If you add underflow check to unsigned numbers, your example raises an 
exception and it is what personally I would expect. The choice to use modular 
arithmetic is the reason why we encounter such an odd behavior.

Of course, with unsigned integers there is more chance to get an underflow than 
an overflow. And this is why we should avoid using modular arithmetic for 
unsigned integers. There is too much risk to encounter an underflow which gets 
unnoticed.

Ironically, in Nim we get overflow checks for signed integers which are very 
unlikely to occur, but not for unsigned integers where they would be really 
helpful.


high(Natural) == high(int)

2021-06-02 Thread lscrd
It would not loop if an exception was raised when computing `a.len - 4`. Signed 
numbers can also wrap around and cause nasty bugs, but fortunately in Nim 
overflows are checked for operations on signed integers.

So, just add underflow/overflow check on unsigned numbers rather than using 
modular arithmetic and the dangerous behavior of unsigned numbers disappears.


Nimble detected as Trojan.Gen.MBT by Symantec Endpoint Protection v14

2021-06-01 Thread lscrd
Yes, it would solve the issue regarding Nim compiler and tools. But it would 
not prevent possible false positives with other programs written in Nim. The AV 
software vendors must refine their criteria regarding what is actually a 
malware written in Nim.

Should we search what in the binaries has actually triggered the quarantining? 
I did that once, but it takes time and it is their job to do that.


Nimble detected as Trojan.Gen.MBT by Symantec Endpoint Protection v14

2021-06-01 Thread lscrd
Yes, but as I already said, this should not occur if AV software vendors did 
correctly their job. They should detect patterns which are specific to malware 
and not flag as suspicious any software written in Nim, especially Nim tools.

Of course, from their point of view, it is preferable to get false positives on 
programs written in a little known language rather than not detect malware. As 
apparently Nim is going to get some popularity as a language to create malware, 
I’m afraid that if AV software vendors continue this way, using Nim on Windows 
will become very painful.

Unfortunately, there is not a big company supporting Nim. If this occurred to 
Go or Rust, I’m pretty sure that the issue would be solved quickly.


Date issue. What happened in 1940?

2021-05-27 Thread lscrd
Yes I understand, but as I said the problem is not only with DST but also with 
time zone changes. When a country changes its timezone as it was the case 
several times in France between 1902 and 1968 (in my second example), this may 
cause troubles when we want to count the number of days between two dates.

As you said, to avoid these problems we should use dates with UTC time zone 
which is the solution I indeed chose. This seems logical: local zone should 
never be used in operations or only when we are sure that there is no time zone 
change or DST.

As regards the parsing of a date, I agree with you that the default should be 
UTC and not the local time zone. But if a time is specified (without explicit 
time zone) should we also use UTC rather than the local time ? This is not so 
obvious.


Date issue. What happened in 1940?

2021-05-27 Thread lscrd
Yes, it seems to be a known problem. I never encountered it before but also 
never played a lot with dates. Better avoid local time is some cases and use 
UTC which is much more predictable.


Date issue. What happened in 1940?

2021-05-27 Thread lscrd
Thanks all for your answers. I indeed live in France and I was aware that there 
are hour changes when France was occupied. But I didn’t know that there was a 
DST on 1940 February 25th (and in fact many DST before war; this is in fact an 
old and unpleasant idea).

So this makes sense… in this example.

But if I want to know how many days there are between 1902 January 1st and 1968 
December 25th (which was my first goal), I get one day less than I expect. At 
first, I thought that it was this missing hour which was never recovered and 
was lost forever. I was wrong.

In France, in 1902, we lived at UTC + 09min 21s as I discovered (Paris meridian 
time), and without DST. In 1968, we lived at UTC+1 without DST. So there is 
actually 50min and 39s missing. This is what I get if I display the detailed 
result rather than the number of days.

If I want to avoid this problem, I have to compute the differences in UTC zone 
(which I finally did) or to use for the ending date a hour such 12:00:00, or to 
do introduce some rounding mechanism.

In my short example in 1940 it was indeed a DST problem, but in my full example 
this is a time zone problem. In trying to locate the problem by limiting the 
time range, I was wrong.

Yes, when dealing with time we have to be very careful.

And by the way, I didn’t know about . This is a 
wonderful site. 


Date issue. What happened in 1940?

2021-05-26 Thread lscrd
No, I checked and 1940 is actually recognized as a leap year. But when 
computing the difference between the two dates, one hour is missing which 
causes the error when converting in days. This is really strange.


Date issue. What happened in 1940?

2021-05-26 Thread lscrd
Hi,

When trying to compute a difference between two dates, I encountered a problem. 
Here a small program to show the issue:


echo (parse("1940-03-01", "-MM-dd") - parse("1940-02-01", 
"-MM-dd")).inDays

Run

And the result is 28 instead of 29. For other years such as 1936 or 1944, the 
result is 29.

If I don’t convert in days, I get `4 weeks and 23 hours` instead of `4 weeks 
and 1 day`. If I create the dates with `initDateTime` rather than `parseTime` I 
encounter the same problem except if I specify that the time zone is UTC.

Thus


let date1 = initDateTime(1, mFeb, year, 0, 0, 0, zone = utc())
let date2 = initDateTime(1, mMar, year, 0, 0, 0, zone = utc())
echo (date2 - date1).inDays

Run

gives 29, but without the zone, it gives 28.

So, it seems that the local() is the reason of this missing hour. I don’t see 
any reason for this behavior. But maybe someone has an explanation.


How to escape colon in the '&' macro in strformat ?

2021-05-23 Thread lscrd
Ah, I see, I had switched to development version. Indeed, it doesn’t compile 
with 1.4.6.


How to escape colon in the '&' macro in strformat ?

2021-05-22 Thread lscrd
This works:


import strformat
echo &"""{"url = http\://example.com"}"""


Run


Python style in Nim

2021-05-18 Thread lscrd
After some reluctance, as I was used to Python list/dict/set comprehensions, I 
finally tried `collect` and I’m rather satisfied with it. I find important that 
it doesn’t cause any overhead.

I appreciate the procedures and templates from `sequtils` too (especially those 
with `it`) but they create copies. They are really nice to use but not very 
efficient.

In Python, we can use comprehension with generators and this is very powerful. 
I’d like to see something like this in Nim.


Int/Floating Point Cast Result

2021-05-17 Thread lscrd
To be clear:


echo int(1.6)# 1
echo toInt(1.6)  # 2


Run


Nim 2.0 -- thoughts

2021-05-15 Thread lscrd
> Can you post code/make a thread about this maybe? I'd wager that if it is 
> slower that it could be helpful to know why.

Good idea. But I will have to find some significant examples. I will think 
about it.


Nim 2.0 -- thoughts

2021-05-15 Thread lscrd
> Maybe because you are not using sink and lent annotations? Also using sink 
> when it's unnecessary may introduce an unwanted copy.

The compiler emits a warning when there is a potential loss of performance with 
sink parameters. But, indeed, I cannot be sure that there is not some tweaking 
to do in my programs when switching to `arc` or `orc`.


Nim 2.0 -- thoughts

2021-05-15 Thread lscrd
What about the performance of `orc`? On my programs, `arc` or `orc` are 
generally slower than the default GC. I don’t know why, as they are expected to 
be faster. In some cases, indeed, I got an impressive boost with `arc/orc`, but 
not very often, alas!

I know that it depends on what the program actually allocate on the heap and, I 
suppose, how it does it. But for me, at least as regards performance, switching 
to `orc` doesn’t seem to be beneficial in general.


Which parameter list delimiter is more "standard"? Commas or semicolons?

2021-05-13 Thread lscrd
Personally, after using colons, I switched to semicolons. I find `proc p(x, y: 
int; s: string` more readable that `proc p(x, y: int, s: string)`. Of course, 
this is only a matter of preference. And I don’t care about what is done in 
other languages. I think that what is important is readability and using 
semicolons improves it.


learn Nim regular expressions - regex, re , NRE

2021-05-02 Thread lscrd
I think it would be inconsistent to mark `re` as deprecated and advise to use 
`regex` instead, while `re` is in the standard library and `regex` is not. If 
`regex` is now the right choice, the first thing to do is to add it in the 
standard library. Deprecation of `re` could follow.


How to make Nim more popular

2021-05-02 Thread lscrd
Yes, this is a long list, but these are mostly drafted tasks. I will look at 
them later. As regards old code, you are right, but I updated it and replaced 
it in some rare cases. For now, all examples in the main tasks run with Nim 
version 1.4, at least until letter Y (letter Z is in progress).

There are some tasks impossible or very difficult to solve in Nim, but some Nim 
experts can find impressive solutions.

@Sixte I didn’t find any task about Datalog. 


nim-1.4.6_x64.zip/bin/nimble.exe reports as Trojan:Win32/Zpevdo.B

2021-05-02 Thread lscrd
I agree. When many AV software have exactly the same behavior on the same 
binaries at the same moment, this is highly suspicious.

And the extraction of a signature from malware is clearly poorly done. No check 
has been done to insure that this signature is specific enough. When the 
compiler of a language if flagged as malware, it’s clear that the signature 
used is pure crap.

This way, they create a lot of false positives and make a language almost 
unusable on Windows platforms.


How to make Nim more popular

2021-05-02 Thread lscrd
Regarding Rosetta contributions, I’m afraid it’s too late. Almost all tasks 
have now a Nim solution. Of course, it is always possible to improve an 
existing solution, to replace it or to add a new solution, using another 
algorithm or another library.

And there is still a lot of work to do on draft tasks (for now).


Why learn NIM

2021-05-01 Thread lscrd
Your "myarray' type has no static bounds, so as soon as you use it, a 
descriptor is created. When you transmit a static array to a parameter of this 
type, the compiler generate code to build a descriptor which contains the lower 
bound, the upper bound and the address of the actual data. Pascal, even in its 
ISO limited version, has open arrays which allow to do the same thing, except 
that the lower bound is not transmitted. In fact, open arrays in Pascal seems 
to be the same thing as open arrays in Nim.

And, you are right. In pascal and in Nim, when accessing the tenth element in 
an open array, this is the tenth independently of the lower bound of the array. 
Checking that we don’t access outside of the array is enough to guarantee 
memory integrity. Ada does better as it checks that, in the procedure, the 
index is always in the bounds of the actual array.

Note that I have encountered other languages which checked the lower bound and 
the upper bound at runtime, using descriptors as in Ada. The French department 
of defense designed a language named LTR3, several years before Ada 83, which 
contained arrays with a dynamically defined lower and upper bound. These where 
not sequences as, as far as I remember, their size was constant. But using 
these arrays in a procedure implied to transmit descriptors and to check the 
bounds during execution.

As soon as we have descriptors for arrays, we are able to create sequences. The 
problem with sequences, is the reallocation when the sequence grows. This is 
certainly the reason why this was seldom encountered in non interpreted 
languages. But Algol 68 has flex strings and flex arrays, a feature which was 
quite modern. And building a compiler for this language was a really a 
challenge in these years.


Why learn NIM

2021-05-01 Thread lscrd
> They may require a small number of additional bytes to track details, say the 
> minimum and maximum indices and probably the length, but many people judge 
> that worth the cost.

They will require additional data only if they are dynamic arrays. If you 
declare `var a: array[5..100] of integer;` in Pascal, there is no loss of 
memory. The compiler knows that the fist element starts at index 5 and will do 
the needed translation when computing the offset (and good compilers avoid the 
subtraction).

If the array is dynamic, you need a descriptor which contains the lower bound 
and the upper bound (or the length). Compared to Nim open arrays, I suppose the 
only difference is the lower bound. As far as I know, open arrays in Nim do not 
keep track of the lower bound of the actual parameter. If you transmit an array 
starting at 1, its lower bound in the procedure will become 0 which I find 
disturbing. It is better to transmit to open arrays only arrays starting at 
index 0 to avoid surprises.


Why learn NIM

2021-05-01 Thread lscrd
If your array starts at index 1 and is stored at some address `a`, when 
generating code to access to `a[i]`, you don’t subtract one to `i`, but you use 
as starting address that of a fictive element `a[0]`. For instance, if the 
array contains 64 bits integers, you use `a - 8` as starting address when 
indexing.

As far as I know, this is C which which introduced 0-based indexes. Most 
languages used 1. In Pascal, the default is one, but may be changed. In APL, it 
was possible to choose the base, one being the default. In PL/1, arrays start 
also at index one.

The reason why C uses 0 is that indexes are actually offsets while in languages 
such as Pascal they are positions. When you write `a[0]` in C, this is 
understood as adding an offset to an address. Arrays are in fact addresses. In 
a language such as Pascal, we don’t think in terms of offset. This is too low 
level. But, thinking this way in C was natural as C intended to replace 
assembler in most situations.


nim-1.4.6_x64.zip/bin/nimble.exe reports as Trojan:Win32/Zpevdo.B

2021-04-29 Thread lscrd
It seems this will become a serious problem for Nim, not only because the 
compiler and the tools will be declared as suspicious, but also because all 
programs produced compiled by the Nim compiler may become suspicious at term.

The AV software vendors seems to have chosen the lazy way to fight the malware 
built in Nim: declare that all Nim binaries are dangerous. It is not easy to 
avoid false positives, but I’m quite sure that they would have been a lot more 
careful if the language was supported by a big company, says a language like 
Rust or Go.

Nim was not in their radars, but thanks to malware makers, it is now. 
Unfortunately, despite the claims of their vendors, AV scanners are not very 
intelligent and still proceed by matching signatures. A poor approach which all 
vendors seems to use with the same lack of precautions. 


XML parsing performance

2021-04-27 Thread lscrd
I agree. And if we choose release mode as default, some people will complain 
that there is not enough assistance when an error occurs.


XML parsing performance

2021-04-26 Thread lscrd
I understand that embedded environments are constrained. But, nowadays, this is 
more for an economical reason than for a technical reason. More memory means 
that each unit costs more and when you want to sell millions of units, this is 
indeed something to take in consideration.

But this position is acceptable only where security is not a strong 
requirement. I know that software in Airbus planes is written in Ada and I 
strongly hope that checks are still there. I know that Ada is used in Ariane 
rockets too and I’m pretty sure that checks are activated: the first Ariane 5 
destroyed itself following some arithmetic overflow.

There are lot of examples where software has killed. Of course, checks 
generated by the compiler are not the panacea but there are important as the 
first line of defense.

And indeed, it is possible to get a good confidence that some parts of code are 
bug free. But this is only possible for small programs. And if using arrays of 
fixed sized prevents some bugs, that doesn’t insure that indexes are always 
valid. It is still possible to access a fixed array out of bounds.

I have seen too much so-called bug free software crashes to be very confident 
in code which doesn’t contain some elementary protections (index checks at 
least, which a compiler can do with a single comparison).


XML parsing performance

2021-04-26 Thread lscrd
The problem with the debug mode is that, for people who never used languages 
compiling to native code, it doesn’t explicitly states that in this mode 
programs will be considerably slower. Many will think that the program will be 
bigger (containing debugging data) which is true indeed, but will not imagine 
how it will be slower.

But I advocate to keep debug mode as default mode as it what we need when 
writing a somewhat complex program. For users accustomed to languages producing 
native code, it is the normal way to proceed: compile in debug mode, then when 
the program is OK, look for optimizations, do some profiling if needed, maybe 
deactivate some checks in parts critical for performance and switch to release 
mode.

But using the release mode as default is also a possibility as it is the normal 
final mode.

As regards the danger mode, well, as its name indicates, it is dangerous. So, 
it should be avoided. For me, producing code which doesn’t contain any code for 
detecting an index out of bounds is a practice from another age.

In fact, I consider that the danger mode is useful for only one thing: compare 
performances with other languages such as C. Of course, checks have a cost and 
in release mode performances are significantly slower, but not that much. And 
rather than deactivate all checks, it is better to deactivate them where the 
gain is important after carefully reviewing the code. 


nim-1.4.6_x64.zip/bin/nimble.exe reports as Trojan:Win32/Zpevdo.B

2021-04-20 Thread lscrd
That’s nothing new. Antivirus designers prefer false positives to false 
negatives. It’s understandable: missing a virus may have terrible consequences 
while false alerts are only an annoyance.

Now, what can be done when there is so much false positives? For sure, there is 
some pattern which has triggered the alert. This may be just a coincidence or 
this can be due to the inclusion of some library.

In my company, we encountered this problem once, but we were lucky: our 
customer used an old version of its antivirus software and updating to last 
version solved the problem. But it was not easy as the customer was very 
suspicious regarding security.


Unicode string print - the four faces look different when printing - why?

2021-04-19 Thread lscrd
You are right. I have tried with classic classic emojis which have code from 
U+1F600 to U+1F64F. And, in my terminal, they are correctly displayed. But the 
four emojis which have code from U+01F466 to 01F469 are not correctly displayed.

I tried to display them in a text editor, with no success. It failed in VSCode 
for instance. But it’s OK in a web browser using the same font! So this is not 
(or not only) a font issue.

The Nim compiler is obviously exonerated here.

It seems that Nim is not guilty here. It’s either a terminal issue or a font 
issue. 


nim program name with spaces

2021-04-03 Thread lscrd
It is perfectly possible to use spaces in a file name: just use non breaking 
space instead of normal space. This works because the compiler accepts Unicode 
characters in module names.

Now, I don’t recommend it; this is very misleading :-).


'ord' cannot be passed to a procvar

2021-03-20 Thread lscrd
And you can do instead:


echo ['A', 'B', 'C', 'D'].mapIt(ord(it))


Run


Defects and CatchableErrors

2021-02-17 Thread lscrd
No, I don’t think so. This works (without --panics:on: of course):


var x = 0
try:
  echo 1 div x
except DivByZeroDefect:
  echo "ok"


Run


Simple recursion really slow?

2021-01-24 Thread lscrd
And I tried the example with options `-d:release --passC:-flto` and decreased 
the time to 14 seconds ! But with `-d:danger --passC:-flto`, this is still more 
than 30 seconds.


Advent of Nim 2020 megathread

2020-12-24 Thread lscrd
About coordinates system for hexagon grids, I found this:



For day 24 AOC, I used the axial coordinates and a set of black tiles too.

In project Euler there are some problems involving hexagon grids.


Advent of Nim 2020 megathread

2020-12-23 Thread lscrd
Doubly linked ring works and I don’t see why they shouldn’t.

My solution uses: – a doubly linked ring which makes easy to remove and insert 
nodes. – a list of nodes allocated once, removed from ring and reinserted when 
needed; – a sequence (not a table but a table would also work) to map values to 
nodes (used to find the destination node from the destination value).


How do you pick an element from a set?

2020-12-16 Thread lscrd
I used sets for Day 16 AOC too. I declared a procedure to retrieve the only 
value of a singleton:


proc value(posSet: set[Position]): Position =
   for pos in posSet: return pos


Run

But your solution is fine. 


Advent of Nim 2020 megathread

2020-12-14 Thread lscrd
Yes and it’s intended. All values in the examples contains only 0 and 1. You 
have to read carefully the detailed description to see that 11 is decimal 11 
and 101 is decimal 101. This is a simple trap but quite effective.


Advent of Nim 2020 megathread

2020-12-08 Thread lscrd
> What a pity, I like the conciseness of scanf for this use case because the 
> pattern visually matches the input and performs parseInt for you, all in one 
> shot.

Yes, you are right and I hesitated to use `scanf` for this reason. I thought 
about using `scanf` then `parseEnum`, as in your last solution, but kept the 
“simpler” but maybe less elegant solution.

@jrfondren I should have thought about it as I already encountered this warning 
in a similar context (when “adding” something). Your solution using “move” is 
fine.


Advent of Nim 2020 megathread

2020-12-08 Thread lscrd
This is a warning and I don’t think you can do anything to prevent it. But in 
this case, the copy is not really a problem.

You can replace `scanf` and the following statement by these two statements:


let fields = line.split(' ')
result.add((fields[0], parseInt(fields[1]))


Run

Personally, I prefer to use enums to represent opcodes, so my code is rather:


let fields = line.split(' ')
result.add((parseEnum[OpCode](fields[0]), parseInt(fields[1])))


Run


Advent of Nim 2020 megathread

2020-12-06 Thread lscrd
There are problems when you do operations between a set of a type and a set of 
a subtype of the type. I reported them here:





In fact, this is probably the same bug with different consequences. And it was 
already known.


Advent of Nim 2020 megathread

2020-12-06 Thread lscrd
I found two bugs with sets when solving the 6th day problem. First bug causes 
an error in C compilation. It seems to be related/identical to an already known 
bug. Second bug is an error in the code produced with makes the program give 
wrong results.


Advent of Nim 2020 megathread

2020-12-03 Thread lscrd
My solutions are here: <https://github.com/lscrd/-AdventOfCode2020>

Please note that I always publish them with some delay.


How to rewrite nim programming langauge to be pythonic as possible?

2020-11-29 Thread lscrd
Yes, you are right. This is the standard rounding in IEEE 754. I suppose that 
with this rounding, errors in one direction better compensates errors in 
another direction.


Strange error message from collections/sets.nim

2020-11-26 Thread lscrd
> Indentation's purpose is to show scope, I'm uncertain if alignment even makes 
> more readable code.

No, indentation is certainly not a way to indicate scoping as in old languages, 
such as Pascal, an IF, a FOR or a WHILE statement doesn’t create a new scope. 
Even in Python an if, a for or a while statement doesn’t create a new scope. In 
most languages, indentation is not syntactically required and is in fact only a 
way to improve readability by making more apparent the syntactical structure.

Now, let’s look at some statement like:


let xx = if expression1: expression2 else: expression3


Run

If the statement is too long, we have to split it. Using only indentation, 
there is several ways, for instance:


let xx = if expression1: expression2
else: expression3

let xx = if expression1: expression2
  else: expression3

let xx = if expression1: expression2
else: expression3

let xx = if expression1: expression2
  else: expression3


Run

But the more logical way needs an extra space for alignment:


let xx = if expression1: expression2
 else: expression3


Run

One can say that the difference is not so important, but for me this is not the 
problem. I simply don’t want to be constrained to use indentation only. 
Syntactically significant indentation is fine for me as it improves readability 
and, so, this is a good constraint. Using indentation only will be 
unacceptable: this would be pushing too far away the bondage and the discipline.

For me, tabs have nothing to do in code. Each time I copied Python code 
containing tabs, its was a nightmare. And having indented and aligned my code 
even when I used punch cards or text editors such as “ed”, I have some 
difficulty to understand where is the problem to use only spaces, moreover when 
modern text editors automatically indent and even deindent.


Strange error message from collections/sets.nim

2020-11-25 Thread lscrd
We want alignment for instance in this case:


if some_long_expression and
   another_long_expression and
   another_one:


Run

Of course, we could use parentheses and write, using only indentation:


if (
  some_long_expression and
  another_long_expression and
  another_one):


Run

but this is silly and ugly.

Of course, alignment is not a requirement but it improves readability. And for 
most languages, indentation is not a requirement either but who would say it is 
useless ?


Changer VSCode pour VSCodium

2020-11-23 Thread lscrd
I have encountered this bug recently after an update of my system (Manjaro). 
This is in fact an Electron bug and downgrading to previous version of Electron 
solved the issue.

The bug caused a warning when compiling from the VSCode terminal. Not a big 
problem. But, for some reason, maybe unrelated, the Nim plugin no longer 
worked. I didn’t investigate to find the real cause of the problem. After 
switching to the previous version of Electron, everything is back to normal, so 
that’s fine for me.

Now, I’m still going to take a look at VSCodium.


Subrange check during initialisation

2020-10-29 Thread lscrd
The check is done for the implicit variable “result” and we get the usual 
warning: `Warning: Cannot prove that 'result' is initialized. This will become 
a compile time error in the future. [ProveInit]`

Why not for a normal variable?


type DiceVal = range[1..6]

proc throwDice(): DiceVal =
  discard

echo throwDice()


Run


Generics constrain with numbers

2020-09-10 Thread lscrd
This way:


func myfunc(number: SomeInteger) =


Run


Any easy way to compare `==` object variants?

2020-09-06 Thread lscrd
To compare records, Nim use the `fields` iterator which doesn’t work for 
variant records.

So, you have to define your own `==` proc:


type
  Obj = object
case type: bool

of false:
  a: int

of true:
  b: int

proc `==`(obj1, obj2: Obj): bool =
  result = obj1.type == obj2.type
  if result:
case obj1.type
of false:
  result = obj1.a == obj2.a
of true:
  result = obj1.b == obj2.b


echo Obj() == Obj()


Run


How can i separate the integer part of a number from its decimal part ?

2020-09-03 Thread lscrd
There is this:



Not widely spoken I suppose 🙂.


How can i separate the integer part of a number from its decimal part ?

2020-09-03 Thread lscrd
> It's really not, as can be seen by reading that Wikipedia article past the 
> first six words.

The problem is that in these six words, fractional part and decimal part are 
presented as synonyms. So, this is bad wording. And, actually, never in the 
article, decimal part is really defined.

There are other sites which provides clear definitions as here: 


The French Wikipedia article is not better and define also both terms as 
synonyms. But we can find this sentence on decimal part (translated in English):

“We find also the term decimal part of the number, in particular for decimal 
numbers.”

Note the “in particular” which I find odd.

In fact, I think that it is generally a bad idea to use Wikipedia as a 
reference. There are too many inaccuracies and inconsistencies.

> Those aren't purists, they are simply ignorant--if you know such people, have 
> them read the Wikipedia article archnim cited

I don’t know such people; this is what is said in the French Wikipedia article 
on fractional part. It cites Scolab as a source, an educative site which indeed 
uses very strange definitions. The translated sentence from Scolab states this 
(with no more explanations):

“In the case of an irrational number, we cannot speak of a fractional part.”

> "fraction" doesn't have anything to do with being rational. a/b where a and b 
> are integers is a rational fraction, but not all fractions are rational.

This is the problem with Wikipedia. Some writer found that the definition given 
was wrong and has added a sentence to provide Scolab point of view. In the 
French Wikipedia text, “fraction” is in fact understood as elements of the 
fractional numbers set which is in fact the set of rationals. This is what 
English Wikipedia names “common fraction”.

> In any case, since computers have finite precision and we're not doing 
> symbolic arithmetic, all these values are rational ...

Of course. When I was a young engineer, in the 80s, I discovered this, the hard 
way, and there was no Wikipedia to help me 🙂.


How can i separate the integer part of a number from its decimal part ?

2020-09-02 Thread lscrd
Yes, it seems that in French “partie décimale” is more frequently used, but 
“partie fractionnaire” is also acceptable:



Some purists say that “fractional part” is inadequate as, for an irrational 
number, this part is not rational and thus cannot be a fraction; but “decimal 
part” is no more adequate as it applies only to decimal numbers.

I don’t remember what term was used when I learned mathematics long time ago. 
But, now, I used “partie fractionnaire” in French and “fractional part” in 
English. That seems more correct.


Blog post about strict funcs

2020-08-29 Thread lscrd
Thanks. That makes sense.


Blog post about strict funcs

2020-08-28 Thread lscrd
This is the pragma {.noSideEffect.} for `add` which causes the error. Adding a 
block {.noSideEffect.} in `p` doesn’t change anything.

But in fact, for now, I don’t want to make the program compile. I just want to 
understand the behavior.

I simplified again my examples (no need for an object) and they now give the 
same result. The first one fails to compile and the second one compiles. The 
proc `add` for an element doesn’t cause any error while the proc for a sequence 
does.


proc p(s: seq[ref int]): seq[ref int] =
  result.add(s)


Run

and


proc p(s: seq[ref int]): seq[ref int] =
  for i in s:
result.add(i)


Run


Blog post about strict funcs

2020-08-28 Thread lscrd
OK, but that doesn’t explain why my second examples compiles. We are in the 
same situation where an alias is created when copying a reference.


  1   2   >