Is inside range - range

Say you have the following type:
type Min = 1..4
You want to check whether some int falls inside Min as you can with sets:
's' in {'a'..'z'}
It is possible to express it more elengantly than:
2 in {low(Min)..high(Min)} #Too many characters
2 in Min #Expecting this conciseness

If you break up the restriction of 1..4 being a type, it's easily possible. 1..4 as a value makes it a Slice instead of a range. I don't know what else you do with Min, but as a slice it supports the in syntax via a contains proc:
echo 2 in 1..4
let Min = 1..4
echo 2 in Min

The issue that you are dealing with is that Min is a type and the right-hand side of the in operator expects an expression. You can handle this either by overloading the in operator as a template that accepts a type argument or by providing a template to convert a type to the underlying range expression.
Overloading in:
type Min = 1..4
template `in`[T](x: T, tp: typedesc[range]): bool =
x in (tp.low .. tp.high)
echo 2 in Min
Converting a type to a range:
type Min = 1..4
template rg(tp: typedesc[range]): expr =
tp.low .. tp.high
echo 2 in rg Min

Related

Iterate (/) a multivalent function

How do you iterate a function of multivalent rank (>1), e.g. f:{[x;y] ...} where the function inputs in the next iteration step depend on the last iteration step? Examples in the reference manual only iterate unary functions.
I was able to achieve this indirectly (and verbosely) by passing a dictionary of arguments (state) into unary function:
f:{[arg] key[arg]!(min arg;arg[`y]-2)}
f/[{0<x`x};`x`y!6 3]
Note that projection, e.g. f[x;]/[whilecond;y] would only work in the scenario where the x in the next iteration step does not depend on the result of the last iteration (i.e. when x is path-independent).
In relation to Rahul's answer, you could use one of the following (slightly less verbose) methods to achieve the same result:
q)g:{(min x,y;y-2)}
q)(g .)/[{0<x 0};6 3]
-1 -3
q).[g]/[{0<x 0};6 3]
-1 -3
Alternatively, you could use the .z.s self function, which recursively calls the function g and takes the output of the last iteration as its arguments. For example,
q)g:{[x;y] x: min x,y; y:y-2; $[x<0; (x;y); .z.s[x;y]]}
q)g[6;3]
-1 -3
Function that is used with '/' and '\' can only accept result from last iteration as a single item which means only 1 function parameter is reserved for the result. It is unary in that sense.
For function whose multiple input parameters depends on last iteration result, one solution is to wrap that function inside a unary function and use apply operator to execute that function on the last iteration result.
Ex:
q) g:{(min x,y;y-2)} / function with rank 2
q) f:{x . y}[g;] / function g wrapped inside unary function to iterate
q) f/[{0<x 0};6 3]
Over time I stumbled upon even shorter way which does not require parentheses or brackets:
q)g:{(min x,y;y-2)}
q){0<x 0} g//6 3
-1 -3
Why does double over (//) work ? The / adverb can sometimes be used in place of the . (apply) operator:
q)(*) . 2 3
6
q)(*/) 2 3
6

Using zero constant as long in a less verbose way [duplicate]

object LPrimeFactor {
def main(arg:Array[String]):Unit = {
start(13195)
start(600851475143)
}
def start(until:Long){
var all_prime_fac:Array[Int] = Array()
var i = 2
(compile:compileIncremental) Compilation failed
integer number too large
Even though I changed the arg type to Long, it's still not fixed.
Pass the argument as a Long (notice the L at the end of the number):
start(600851475143L)
// ^
To create a Long literal you must add L to the end of it.
start(600851475143L)
Please remember literals values, if you has not any type direct suffix, the compiler try to get your numeric type values, such as 600851475143 as type Int, which is 32-bit length, two complement representation
MIN_VALUE = -2147483648(- 2 ^ 31)
MAX_VALUE = 2147483647(2 ^ 31 - 1)
So please add right suffix on the literal value, as 600851475143L

Is there a reason why the shift operators (>> and <<) don't work on BitwiseOperationsType?

I was thinking of making an integer power function in Swift based on this StackOverflow answer:
func **<T : IntegerType>(var base: T, var exponent: T) -> T {
var result: T = 1
assert(exponent >= 0, "Exponent cannot be negative")
while exponent > 0 {
if exponent & 1 != 0 {
result *= base
}
exponent = exponent >> 1
base *= base
}
return result
}
I figured I could use generics to implement the function so that it would work with any integer type.
Unfortunately, I get an error when I attempt to use exponent >> 1:
Binary operator '>>' cannot be applied to two 'T' operands
Checking the function definitions for >>, I see that there is one for each of the ten integer types, but no other ones are defined. I was surprised therefore that all the other operators were working, such as &, but I noticed that & was actually defined to work on all types which conform to BitwiseOperationsType, which IntegerType appears to conform to.
Is there a reason why the >> and << operators are not implemented for BitwiseOperationsType?

kdb+/q: Check if argument has been supplied to the function call

Say we have function fun with two arguments, second one is optional.
How to check within the function whether the second, optional argument has been supplied and act accordingly?
fun: {[x;optarg] $["optarg was supplied" like "optarg was supplied";"behavior 1"; "behavior 2"] }
fun[1;2] / behavior 1
fun[1] / behavior 2
```
I don't think this is possible. Supplying less than the specified number of arguments result in a projection.
A good alternative is to have your function accept one argument - a list. And then you can check for the existence of each element of the list.
f:{[l] $[1=count[l];
/ do something with first arg only;
/ do something with both args ]
}
Or you could have the function accept a dictionary (this allows you to set default values in the function).
q)f:{[dict] def:`a`b`c!10 20 30;
def:def upsert dict;
:def[`a] + def[`b] + def[`c] }
q)f[`a`b!5 10]
45
q)f[`a`c!5 10]
35
You can't check for number of arguments, kdb+ will report rank error when number of arguments is more than expected. But there is a workaround which will result in function which will accept any number of arguments:
q)func:('[{$[1=count x;"one";"more"]};enlist])
q)func[1]
"one"
q)func[1;2]
"more"
q)func[1;2;3]
"more"
Here is an example:
q)func:('[{$[1=count x;x[0];sum x]};enlist])
q)func[1]
1
q)func[1;2]
3
q)func[1;2;4]
7
q)func[1;2;4;7]
14
func:('[{
inputs:(`a_Required`b_Required`c_Optional`d_Optional);
optionalDefaults:`c_Optional`d_Optional!(0b;1b);
if[(count inputs)<count x;-1"Too Many input arguments";:()];
data:inputs xcols optionalDefaults, (!) . (numInputs:count x)#'(inputs;x);
show data;
data
};enlist]
)

Strings Expansion is changing order or the string

I'm trying to so some normal variable expansion in a string and, when it's in a function, it comes out out-of-order.
function MakeMessage99($startValue, $endValue) { "Ranges from $startValue to $endValue" }
MakeMessage99(1, 100)
This returns Ranges from 1 100 to then it should return Ranges from 1 to 100
Functions in powershell shouldn't use parenthesis to enclose parameters. Instead:
PS C:\> MakeMessage99 1 100
Ranges from 1 to 100
Where MakeMessage is your function, "1" is a parameter in the first position, and "100" is a parameter in the second position. According to about_Functions_Advanced_Parameters:
By default, all function parameters are positional. Windows PowerShell assigns position numbers to parameters in the order in which the parameters are declared in the function.
Powershell has several ways to check input going in. You could cast the input as a numeric type. There are also baked-in validation methods for parameters that may prevent this sort of error in the future. If you really want an integer, a simple cast would cause an array to be invalid input. For example:
function MakeMessage99 {
Param
(
[int]$startValue,
[int]$endValue
)
"Ranges from $startValue to $endValue"
}
You could also explore range validation (such as [ValidateRange(0,100)]), pattern validation (such as [ValidatePattern("[0-9][0-9][0-9][0-9]")] to validate a four-digit number) or other validation attributes listed in the link above.
This is a common pitfall in PowerShell. When you invoke...
MakeMessage99(1, 100)
...you're actually passing an array containing the values 1 and 100 as the first parameter. To pass 1 as the first parameter and 100 as the second parameter, use...
MakeMessage99 1 100