How to mark non-pure function as pure in Nim - nim-lang

Is there a way to mark non-pure function p as pure? Maybe with some pragma?
I'm using p for debug, and it can't be used inside pure func procs.
playground
proc p(message: string): void = echo message
func purefn: void =
p "track"
purefn()
Error:
/usercode/in.nim(3, 6) Error: 'purefn' can have side effects

Well, for a start you can just use debugEcho instead of echo - it has no side effects (and it's specifically made for use-cases like that).
In other cases you can "lie" to the compiler by doing:
proc p(message: string) =
{.cast(noSideEffect).}:
echo message
func purefn =
p "track"
purefn()
as described in https://nim-lang.org/docs/manual.html#pragmas-nosideeffect-pragma, but I would advise against it.

For your case, you can use debugEcho inside of echo which fakes having no side effects.
Other than that, you can use the {.cast(noSideEffect).} pragma if you're not using echo in your real code:
proc p(message: string): void = echo message
func purefn: void =
{.cast(noSideEffect).}:
p "track"
purefn()

Related

How to return `void` as a generic return type in Nim?

How to handle a case when proc returns void as generic return type T?
Example - when reading a file we have return value - the file content, but when writing a file there's no return value.
playground
import sugar
proc open_file[T](path: string, cb: (proc (file: string): T)): T =
cb("file descriptor")
proc read_file(path: string): string =
open_file(path, (file) => "file content")
proc write_file(path, content: string): void =
discard open_file(path, proc (file: auto): bool =
echo "writing content to file"
false
)
echo read_file("/some-path")
write_file("/some-path", "some content")
Is there a better way than a workaround in this example - when we returning something (false) and discarding it?
You're making a big misunderstanding here - the discard that you use is related to the return value in open_file, it's not related to the void in your write_file at all.
void as a return type is superficial (doesn't need to be specified when there's no return type) and it literally means "return nothing" (it's not like C's void), but Nim requires you to handle return values from any procedures unless they are marked as {.discardable.}
So in your code example, there are no workarounds at all, it's normal Nim code (except for the fact that void is not required to be written) - see https://nim-lang.org/docs/manual.html#statements-and-expressions-discard-statement

How to create functional pipes for functions/methods in Groovy?

I want to create pipes to connect Groovy function (method) calls like its done in other functional languages, such as F#:
let print message =
printf "%s" message
// "Hello World" will be passed as a parameter to the print function
"Hello World" |> print
There is a naive implementation using the or operator:
Object.metaClass.or { it -> it(delegate)}
def print = { msg ->
println msg
}
"Hello World" | print //Hello World
But it only works for functions with 1 parameter. For more parameters, rcurry has to be used:
Object.metaClass.or { it -> it(delegate)}
def print = { msg1, msg2 ->
println msg1 + msg2
}
"Hello World" | print.rcurry('!!!') //Hello World!!!
Is there a way to get rid of the rcurry method and make the Groovy code more similar to F#'s? BTW, this naive implementation only works for Groovy script files. How do I make it work also for class files?
Notice: There are other questions about pipes in Groovy but these are about pipes for shell commands not functions.
It looks like you just want with and using .& to convert methods to Closures, and >> for function composition.
public static String addExclamations(String s) {
return s + "!!!"
}
Closure printUppercase = { String s -> println s.toUpperCase() }
"Hello World".with (this.&addExclamations >> printUppercase)
A real world example I find myself using all the time:
import groovy.json.JsonOutput
[a:[b:'c', d:'e']].with (JsonOutput.&toJson >> JsonOutput.&prettyPrint)
I'm not sure what you're getting at with the multiparameter stuff, because the various curry solutions seem sensible to me, but you've dismissed that... perhaps I can edit this answer if you can give an example of how you would like it to look?

Function Overloading in golang [duplicate]

I'm porting a C library to Go. A C function (with varargs) is defined like this:
curl_easy_setopt(CURL *curl, CURLoption option, ...);
So I created wrapper C functions:
curl_wrapper_easy_setopt_str(CURL *curl, CURLoption option, char* param);
curl_wrapper_easy_setopt_long(CURL *curl, CURLoption option, long param);
If I define function in Go like this:
func (e *Easy)SetOption(option Option, param string) {
e.code = Code(C.curl_wrapper_easy_setopt_str(e.curl, C.CURLoption(option), C.CString(param)))
}
func (e *Easy)SetOption(option Option, param long) {
e.code = Code(C.curl_wrapper_easy_setopt_long(e.curl, C.CURLoption(option), C.long(param)))
}
The Go compiler complains:
*Easy·SetOption redeclared in this block
So does Go support function (method) overloading, or does this error mean something else?
No it does not.
See the Go Language FAQ, and specifically the section on overloading.
Method dispatch is simplified if it doesn't need to do type matching as well. Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.
Update: 2016-04-07
While Go still does not have overloaded functions (and probably never will), the most useful feature of overloading, that of calling a function with optional arguments and inferring defaults for those omitted can be simulated using a variadic function, which has since been added. But this comes at the loss of type checking.
For example: http://changelog.ca/log/2015/01/30/golang
According to this, it doesn't: http://golang.org/doc/go_for_cpp_programmers.html
In the Conceptual Differences section, it says:
Go does not support function overloading and does not support user defined operators.
Even though this question is really old, what I still want to say is that there is a way to acheive something close to overloading functions. Although it may not make the code so easy to read.
Say if you want to overload the funtion Test():
func Test(a int) {
println(a);
}
func Test(a int, b string) {
println(a);
println(b);
}
The code above will cause error. However if you redefine the first Test() to Test1() and the second to Test2(), and define a new function Test() using go's ..., you would be able to call the function Test() the way it is overloaded.
code:
package main;
func Test1(a int) {
println(a);
}
func Test2(a int, b string) {
println(a);
println(b);
}
func Test(a int, bs ...string) {
if len(bs) == 0 {
Test1(a);
} else {
Test2(a, bs[0]);
}
}
func main() {
Test(1);
Test(1, "aaa");
}
output:
1
1
aaa
see more at: https://golangbyexample.com/function-method-overloading-golang/ (I'm not the author of this linked article but personally consider it useful)
No, Go doesn't have overloading.
Overloading adds compiler complexity and will likely never be added.
As Lawrence Dol mentioned, you could use a variadic function at the cost of no type checking.
Your best bet is to use generics and type constraints that were added in Go 1.18
To answer VityaSchel's question, in the comments of Lawrence's answer, of how to make a generic sum function, I've written one below.
https://go.dev/play/p/hRhInhsAJFT
package main
import "fmt"
type Number interface {
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
}
func Sum[number Number](a number, b number) number {
return a + b
}
func main() {
var a float64 = 5.1
var b float64 = 3.2
println(Sum(a, b))
var a2 int = 5
var b2 int = 3
println(Sum(a2, b2))
}

Difference between String and StaticString

I was browsing the docs, and I found StaticString. It states:
An simple string designed to represent text that is "knowable at compile-time".
I originally thought that String has the same behaviour as NSString, which is known at compile time, but it looks like that I was wrong. So my question is when should we use StaticString instead of a String, and is the only difference is that StaticString is known at compile-time?
One thing I found is
var a: String = "asdf" //"asdf"
var b: StaticString = "adsf" //{(Opaque Value), (Opaque Value), (Opaque Value)}
sizeofValue(a) //24
sizeofValue(b) //17
So it looks like StaticString has a little bit less memory footprint.
It appears that StaticString can hold string literals. You can't assign a variable of type String to it, and it can't be mutated (with +=, for example).
"Knowable at compile time" doesn't mean that the value held by the variable will be determined at compile time, just that any value assigned to it is known at compile time.
Consider this example which does work:
var str: StaticString
for _ in 1...10 {
switch arc4random_uniform(3) {
case 0: str = "zero"
case 1: str = "one"
case 2: str = "two"
default: str = "default"
}
print(str)
}
Any time you can give Swift more information about how a variable is to be used, it can optimize the code using it. By restricting a variable to StaticString, Swift knows the variable won't be mutated so it might be able to store it more efficiently, or access the individual characters more efficiently.
In fact, StaticString could be implemented with just an address pointer and a length. The address it points to is just the place in the static code where the string is defined. A StaticString doesn't need to be reference counted since it doesn't (need to) exist in the heap. It is neither allocated nor deallocated, so no reference count is needed.
"Knowable at compile time" is pretty strict. Even this doesn't work:
let str: StaticString = "hello " + "world"
which fails with error:
error: 'String' is not convertible to 'StaticString'
StaticString is knowable at compile time. This can lead to optimizations. Example:
EDIT: This part doesn't work, see edit below
Suppose you have a function that calculates an Int for some String values for some constants that you define at compile time.
let someString = "Test"
let otherString = "Hello there"
func numberForString(string: String) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
let some = numberForString(someString)
let other = numberForString(otherString)
Like this, the function would be executed with "Test" and "Hello there" when it really gets called in the program, when the app starts for example. Definitely at runtime. However if you change your function to take a StaticString
func numberForString(string: StaticString) -> Int {
return string.stringValue.unicodeScalars.reduce(0) { $0 * 1 << 8 + Int($1.value) }
}
the compiler knows that the passed in StaticString is knowable at compile time, so guess what it does? It runs the function right at compile time (How awesome is that!). I once read an article about that, the author inspected the generated assembly and he actually found the already computed numbers.
As you can see this can be useful in some cases like the one mentioned, to not decrease runtime performance for stuff that can be done at compile time.
EDIT: Dániel Nagy and me had a conversation. The above example of mine doesn't work because the function stringValue of StaticString can't be known at compile time (because it returns a String). Here is a better example:
func countStatic(string: StaticString) -> Int {
return string.byteSize // Breakpoint here
}
func count(string: String) -> Int {
return string.characters.count // Breakpoint here
}
let staticString : StaticString = "static string"
let string : String = "string"
print(countStatic(staticString))
print(count(string))
In a release build only the second breakpoint gets triggered whereas if you change the first function to
func countStatic(string: StaticString) -> Int {
return string.stringValue.characters.count // Breakpoint here
}
both breakpoints get triggered.
Apparently there are some methods which can be done at compile time while other can't. I wonder how the compiler figures this out actually.

Which programming languages allow default values for method parameters?

I'm curious which languages allow you to do something like this:
method foo(String bar = "beh"){
}
If you call foo like this:
foo();
bar will be set to "beh", but if you call like this:
foo("baz");
bar will be set to "baz".
almost all Lisps
Ruby
Python
C++
C#
Visual Basic.NET
Tcl
Visual Basic
Ioke
Seph
Cobra
Nemerle
Mirah
Delphi
Groovy
PHP
Fancy
Scala
PHP:
function foo($var = "foo") {
print $var;
}
foo(); // outputs "foo"
foo("bar"); // outputs "bar"
Python:
def myFun(var = "foo"):
print var
Ruby:
def foo(var="foo")
print var
end
Groovy:
def foo(var="foo") {
print var
}
Ones I can think of
C# 4.0
C++
VB.Net (all versions)
VB6
F# (members only)
Powershell
IDL
Ruby
Racket provides this, as well as keyword arguments:
(define (f x [y 0]) (+ x y))
(f 1) ; => 1
(f 10 20) ; => 30
(define (g x #:y [y 0]) (- x y))
(g 1) ; => 1
(g 10 #:y 20) ; => -10
They're described in the documentation.
Delphi has allowed this since about version 5 - released in 1999
procedure foo(const bar: string = 'beh');
begin
...
end;
foo;
foo('baz');
Perl does with Method::Signatures.
Python:
def foo(bar = value):
# This function can be invoked as foo() or foo(something).
# In the former case, bar will have its default value.
pass
as of c# 4.0 you can now have default params. Finally!
Also C++, Ruby and VB
TCL provides this functionality
proc procName {{arg1 defaultValue} {arg2 anotherDefaultValue}} {
# proc body
}
D:
void foo(int x, int y = 3)
{
...
}
...
foo(4); // same as foo(4, 3);
Fantom:
class Person
{
Int yearsToRetirement(Int retire := 65) { return retire - age }
Int age
}
Java has a workaround.
You can have the foo method with no parameters that calls the foo method with parameters setting the default value, like this:
void foo() {
foo("beh");
}
void foo(String bar) {
this.bar = bar;
}
Add to the list Realbasic (indeed Realbasic has almost every nice feature of every language I can think of, including introspection and sandboxed scripting).
Python. (But watch out for mutables per http://effbot.org/zone/default-values.htm )
And plenty of languages, including C, allow variable numbers of parameters which effectively lets you do the same thing.
In many modern scripting languages, including PHP, JavaScript, and Perl, a better idiom for handling such things is to allow an associative array or object as a parameter, and then assign defaults if needed.
e.g.
function foo( options ){
if( options.something === undefined ){
options.something = some_default_value;
}
...
}
This eliminates the necessity of putting the defaultable values at the end of the list of parameters and remembering all the stuff you don't want to override.
As always -- use in moderation.
You can do it in PL/SQL.
I know Python allows this, while C,C++ don't.

Resources