Skip to content

Code Snippets Comparisons

Ilya Sher edited this page Jun 8, 2019 · 16 revisions

This page contains random pieces of code and their counterparts in NGS, reminiscent of Rosetta Code.

I frequently feel the need to see how a piece of code would look in NGS. Here are some of the comparisons.

User Agent String Building (Go)

Original: https://github.com/moby/moby/blob/4f0d95fa6ee7f865597c03b9e63702cdcb0f7067/pkg/useragent/useragent.go

Overhead

Go

package useragent // import "github.com/docker/docker/pkg/useragent"

import (
	"strings"
)

NGS

Currently none. Maybe later, when NGS explicitly supports very large projects.

Defining the Type and Basic Operations on the Type

Go

// VersionInfo is used to model UserAgent versions.
type VersionInfo struct {
	Name    string
	Version string
}

NGS

doc VersionInfo is used to model UserAgent versions.
type VersionInfo

F init(vi:VersionInfo, name:Str, version:Str) init(args())

F Str(vi:VersionInfo) "${vi.name}/${vi.version}"

Version Info Validation

Go

func (vi *VersionInfo) isValid() bool {
	const stopChars = " \t\r\n/"
	name := vi.Name
	vers := vi.Version
	if len(name) == 0 || strings.ContainsAny(name, stopChars) {
		return false
	}
	if len(vers) == 0 || strings.ContainsAny(vers, stopChars) {
		return false
	}
	return true
}

NGS

F is_valid(vi:VersionInfo) {
	STOP_CHARS = " \t\r\n/"

	F contains_any(s:Str, chars:Str) s.any(X in chars)

	[vi.name, vi.version].all(F(field) {
		field and not(field.contains_any(STOP_CHARS))
	})
}

Creating the Full User Agent String

Go

func AppendVersions(base string, versions ...VersionInfo) string {
	if len(versions) == 0 {
		return base
	}

	verstrs := make([]string, 0, 1+len(versions))
	if len(base) > 0 {
		verstrs = append(verstrs, base)
	}

	for _, v := range versions {
		if !v.isValid() {
			continue
		}
		verstrs = append(verstrs, v.Name+"/"+v.Version)
	}
	return strings.Join(verstrs, " ")
}

NGS

F append_versions(base:Str, *version_info) {
	guard version_info.all(VersionInfo)
	not(version_info) returns base
	base +? ' ' + version_info.filter(is_valid).map(Str).join(' ')
}

TC39 proposal for Object.fromEntries (JavaScript)

Original: https://github.com/tc39/proposal-object-from-entries

In this comparison JavaScript Object is translated as NGS Hash. That's the most appropriate NGS data structure for the presented use case in the proposal.

The proposed functionality

JavaScript (proposed functionality)

obj = Object.fromEntries([['a', 0], ['b', 1]]); // { a: 0, b: 1 }

NGS (existing functionality)

obj = Hash([['a', 0], ['b', 1]])

Current code without the proposed feature

JavaScript

obj = Array.from(map).reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val }), {});

NGS

# Alternative 1
obj = collector/{} Arr(mymap).each(F(pair) collect(pair[0], pair[1]))

# Alternative 2 - implementation of the Hash() above, in "NGS (existing functionality)"
obj = collector/{} Arr(mymap).each(F(pair) collect(*pair))

Object-to-object property transformations

From the proposal's "Motivating examples"

JavaScript (proposed functionality)

obj = { abc: 1, def: 2, ghij: 3 };
res = Object.fromEntries(
	Object.entries(obj)
	.filter(([ key, val ]) => key.length === 3)
	.map(([ key, val ]) => [ key, val * 2 ])
);

// res is { 'abc': 2, 'def': 4 }

NGS (existing functionality)

Transformation to and from Array is not need as there are convenient methods for manipulating Hashes.

# Alternative 1
obj = { "abc": 1, "def": 2, "ghij": 3 }
res = obj.filterk(F(k) k.len() === 3).mapv(X*2)

# Alternative 2 - shorter syntax
obj = { "abc": 1, "def": 2, "ghij": 3 }
res = obj.filterk({A.len() === 3}).mapv(X*2)

GitHub Issues Numbers and Titles

Original: https://elv.sh/

Elvish

curl https://api.github.com/repos/elves/elvish/issues |
	from-json | explode (all) |
	each [issue]{ echo $issue[number]: $issue[title] } |
	head -n 11

NGS

Alternative 1 - more readable

issues = ``curl https://api.github.com/repos/elves/elvish/issues``
issues.limit(11).map(F(issue) "${issue.number}: ${issue.title}").each(echo)
  • ``..`` is a syntax for "execute and parse output".
  • issues is a data structure corresponding to the parsed JSON from the API call.
  • .limit(n) limits the number of items by taking first n items.

Alternative 2 - shorter

``curl https://api.github.com/repos/elves/elvish/issues``.limit(11) / {"${A.number}: ${A.title}"} % echo
  • / is a "map" operator: x / f is equivalent to x.map(f). Use of / is not recommended for clarity reasons.
  • { ... } is a shortcut syntax for anonymous function. { ... } is equivalent to F(A=null, B=null, C=null) { ... }.
  • % is an "each" operator: x % f is equivalent to x.each(f). Use of % is not recommended for clarity reasons.

Astronauts from JSON API

Original: https://acha.ninja/blog/json-in-janet-shell/

Janet Shell

(import json)
(var astronauts-in-space
  (json/decode ($$ curl http://api.open-notify.org/astros.json)))
(each astronaut (astronauts-in-space "people")
  (print
	"Name: " (astronaut "name") 
	", Craft: " (astronaut "craft")))

NGS

Alternative 1 - closer to original

astronauts_in_space = ``curl http://api.open-notify.org/astros.json``
each(astronauts_in_space.people, F(astronaut) {
	echo("Name: ${astronaut.name}, Craft: ${astronaut.craft}")
})
  • ``..`` is a syntax for "execute and parse output".

Output:

Name: Oleg Kononenko, Craft: ISS
Name: David Saint-Jacques, Craft: ISS
Name: Anne McClain, Craft: ISS
Name: Alexey Ovchinin, Craft: ISS
Name: Nick Hague, Craft: ISS
Name: Christina Koch, Craft: ISS

Alternative 2 - formatted table output

astronauts_in_space = ``curl http://api.open-notify.org/astros.json``
t = Table2::Table(astronauts_in_space.people)
echo(t)

Output:

name                 craft
Oleg Kononenko       ISS  
David Saint-Jacques  ISS  
Anne McClain         ISS  
Alexey Ovchinin      ISS  
Nick Hague           ISS  
Christina Koch       ISS  
name                 craft