Replace all variables in Sprintf with same variable - string

Is it possible using fmt.Sprintf() to replace all variables in the formatted string with the same value?
Something like:
val := "foo"
s := fmt.Sprintf("%v in %v is %v", val)
which would return
"foo in foo is foo"

It's possible, but the format string must be modified, you must use explicit argument indicies:
Explicit argument indexes:
In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a '*' for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.
Your example:
val := "foo"
s := fmt.Sprintf("%[1]v in %[1]v is %[1]v", val)
fmt.Println(s)
Output (try it on the Go Playground):
foo in foo is foo
Of course the above example can simply be written in one line:
fmt.Printf("%[1]v in %[1]v is %[1]v", "foo")
Also as a minor simplification, the first explicit argument index may be omitted as it defaults to 1:
fmt.Printf("%v in %[1]v is %[1]v", "foo")

You could also use text/template:
package main
import (
"strings"
"text/template"
)
func format(s string, v interface{}) string {
t, b := new(template.Template), new(strings.Builder)
template.Must(t.Parse(s)).Execute(b, v)
return b.String()
}
func main() {
val := "foo"
s := format("{{.}} in {{.}} is {{.}}", val)
println(s)
}
https://pkg.go.dev/text/template

Related

What is being copied when passing a string as parameter?

In Golang, everything is passed by value. If I pass an array "directly" (as opposed as passing it by pointer), then any modification made in the function will be found outside of it
func f(a []int) {
a[0] = 10
}
func main() {
a := []int{2,3,4}
f(a)
fmt.Println(a)
}
Output: [10 3 4]
This is because, to my understanding, an array constitutes (among other things) of a pointer to the underlying data array.
Unless I am mistaken (see here) strings also constitute (along with a "len" object) of a pointer (a unsafe.Pointer) to the underlying data. Hence, I was expecting the same behaviour as above but, apparently, I was wrong.
func f(s string) {
s = "bar"
}
func main() {
s := "foo"
f(s)
fmt.Println(s)
}
Output: "foo"
What is happening here with the string? Seems like the underlying data is being copied when the string is passed as argument.
Related question: When we do not wish our function to modify the string, is it still recommended to pass large strings by pointer for performance reasons?
A string has two values in it: pointer to an array, and the string length. When you pass string as an argument, those two values are copied, not the underlying array.
There is no way to modify the contents of string other than using unsafe. When you pass a *string to a function and that function modifies the string, the function simply modifies the string to point to a different array.

What does this strange line do?

A pull request has been done with a new test for the Rust compiler. It verifies that a strange line can compile:
fn main() {
let val = !((|(..):(_,_),__#_|__)((&*"\\",'#')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
What does this line do exactly?
Let's break it down! First, I reformatted the line to somewhat increase "readability".
let val = !(
(
|(..): (_, _), __#_| __
)(
(
&*"\\",
'#'
) /**/,
{}
)
==
{
&[..=..][..];
}
)//
;
It starts with let val = and ends with //<newline>;. So it's a simple let-binding of the form let val = ⟨v⟩;. Let's discuss what ⟨v⟩ does:
A negation via the not operator: !( ⟨_⟩ )
A comparison via ==: ⟨lhs⟩ == ⟨rhs⟩
⟨lhs⟩: a function call of a closure ( ⟨closure⟩ )( ⟨args⟩ )
⟨closure⟩: a closure definition |⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
⟨first_param⟩: (..): (_, _). This parameter has a type annotation (_, _) meaning that it is a 2-tuple. The pattern (where normally, you would find a single name) is (..) which means: a tuple, but ignore all elements of it.
⟨second_param⟩: __#_. This is a pattern usually known from match bindings: name # pattern. So the actual pattern is _ (which doesn't bind anything) and the value is bound via # to the name __ (two underscores, which is a kind of valid identifier).
⟨body⟩: __. This is just the identifier which we bound the second parameter to. So the closure is basically equivalent to |_, x| x.
⟨args⟩: a list of two arguments with an inline comment /**/ in between: ⟨first_arg⟩/**/, ⟨second_arg⟩
⟨first_arg⟩: (&*"\\", '#'). This is simply a 2-tuple where the first element is a string containing a backslash and the second is the char '#'. The &* for the first element cancels out.
⟨second_arg⟩: {}. This is an empty block which has the type (). So as second argument, a unit is passed.
⟨rhs⟩: a braced block with one statement inside: { ⟨stmt⟩; }. Note that this is a statement, with a semicolon. This means the result is not returned from the block. Instead the block returns () just as the empty block {}.
⟨stmt⟩: an indexing expression { &⟨collection⟩[⟨index⟩] }.
⟨collection⟩: [..=..]. This is an array with one element. The element is ..= .. which is a RangeToInclusive where end of the range is the RangeFull written ...
⟨index⟩: ... This is just the RangeFull again.
So in summary: we compare the result of calling a closure to a braced block which evaluates to (). The closure is basically |_, x| x and the second argument we pass to it is {} (which evaluates to ()), so the whole closure calling expression evaluates to ().
This means the whole thing is equivalent to:
let val = !( () == () );, which is equivalent to:
let val = !( true );, which is equivalent to:
let val = false;

Best way to convert string of digits into its numerical big.Rat value

I'm working with math/big.
I was wondering if somebody knows a short way to convert a string of digits like "2023930943509509" to a big.Rat type value.
I know .SetString() can be used for big.Int types, but can the same be done for the Rat type?
You don't have to learn these methods and functions by heart, whenever you look for something, check the package documentation. The doc of the package in question can be found here: math/big.
As you can see in the doc, there is a Rat.SetString() method for the big.Rat type too which you can use for this purpose:
func (z *Rat) SetString(s string) (*Rat, bool)
SetString sets z to the value of s and returns z and a boolean indicating success. s can be given as a fraction "a/b" or as a floating-point number optionally followed by an exponent. The entire string (not just a prefix) must be valid for success. If the operation failed, the value of z is un- defined but the returned value is nil.
Example using it:
r := big.NewRat(1, 1)
if _, ok := r.SetString("2023930943509509"); !ok {
fmt.Println("Failed to parse the string!")
}
fmt.Println(r)
fmt.Println(r.FloatString(2))
Output (try it on the Go Playground):
2023930943509509/1
2023930943509509.00

Scala Filter Chars from String

I've got the following code which is supposed to count the numbers of times a character appears in a string.
def filter[T] (l: List[T], stays: T ⇒ Boolean): List[T] = {
if( l == Nil ) return Nil
if (stays(l.head) == true) l.head :: filter(l.tail, stays)
else filter(l.tail, stays)
}
def countChar(s: String): List[(Char, Int)] = {
if (s == "") Nil
else (s(0), s.count(_ == s(0))) :: countChar(filter(s.toList, _ == s(0)).mkString)
}
Now my problem is that in
filter(s.toList, _ == s(0))
I get the error of: missing parameter type. I understand that this comes from nesting the function?
How can I fix this to work? I know that String has some methods to do what I want but I'd like to use my own filter method.
That's a limitation of Scala compiler: it tries to figure out what type T in filter should be, using both arguments l and stays. But it fails because the type of stays argument is unspecified.
If you don't want to specify the type of stays argument every time (i.e., filter(s.toList, (_: Char) == s(0)), you can split filter's argument list into two:
def filter[T] (l: List[T])(stays: T ⇒ Boolean): List[T]
Then Scala will know that T is Char by the time it analyzes the type of stays. You can call this filter with filter(l.tail)(stays).

What is the difference between []string and ...string in golang?

In the Go language,
[]string is a string array
and we also use ...string as a parameter.
What is the difference?
Function definition:
func f(args ...string) {}
Can I call this function like below?
args := []string{"a", "b"}
f(args)
[]string is a string array
Technically it's a slice that references an underlying array
and we also use ...string as a parameter.
What is the difference?
With respect to the structure, nothing really. The data type resulting from both syntax is the same.
The ... parameter syntax makes a variadic parameter. It will accept zero or more string arguments, and reference them as a slice.
With respect to calling f, you can pass a slice of strings into the variadic parameter with the following syntax:
func f(args ...string) {
fmt.Println(len(args))
}
args := []string{"a", "b"}
f(args...)
This syntax is available for either the slice built using the literal syntax, or the slice representing the variadic parameter (since there's really no difference between them).
http://play.golang.org/p/QWmzgIWpF8
Both create an array of strings, but the difference is in how it is called.
func f(args ...string) {
}
// Would be called like this:
f("foo","bar","baz");
This allows you to accept a variable number of arguments (all of the same type)
A great example of this is fmt.Print and friends, which can accept as few or as many arugments as you want.
Here is what you want:
var args []string = []string{"A", "B", "C"}
func Sample(args ...string) {
for _, arg := range args {
fmt.Println(arg)
}
}
func main() {
Sample(args...)
}
Play: http://play.golang.org/p/N1ciDUKfG1
It simplifies your function parameters. Here is an example(https://play.golang.org/p/euMuy6IvaM):
Method SampleEllipsis accepts from zero to many parameters of the same type but in the method SampleArray it is mandatory args to be declared.
package main
import "fmt"
func SampleEllipsis(args ...string) {
fmt.Printf("Sample ellipsis : %+v\n",args)
}
func SampleArray(args []string) {
fmt.Println("Sample array ")
SampleEllipsis(args...)
}
func main() {
// Method one
SampleEllipsis([]string{"A", "B", "C"}...)
// Method two
SampleEllipsis("A", "B", "C")
// Method three
SampleEllipsis()
// Simple array
SampleArray([]string{"A", "B", "C"})
// Simple array
SampleArray([]string{})
}
Returns :
Sample ellipsis : [A B C]
Sample ellipsis : [A B C]
Sample ellipsis : []
Sample array
Sample ellipsis : [A B C]
Sample array
Sample ellipsis : []

Resources