Function returning 2 types based on input in Perl. Is this a good approach? - perl

i have designed a function which can return 2 different types based on the input parameters
ex: &Foo(12,"count") -> returns record count from DB for value 12
&Foo(12,"details") -> returns resultset from DB for value 12 in hash format
My question is is this a good approach? in C# i can do it with function overload.

Please think what part of your code gets easier by saying
Foo(12, "count")
instead of
Foo_count(12)
The only case I can think of is when the function name ("count") itself is input data. And even then do you probably want to perform some validation on that, maybe by means of a function table lookup.
Unless this is for an intermediate layer that just takes a command name and passes it on, I'd go with two separate functions.
Also, the implementation of the Foo function would look at the command name and then just split into a private function for every command anyway, right?

additionally you might consider the want to make foo return the details if you wanted a list.
return wantarray ? ($num, #details) : $num;

Related

Apache AGE - Creating Functions With Multiple Parameters

I was looking inside the create_vlabel function and noted that to get the graph_name and label_name it is used graph_name = PG_GETARG_NAME(0) and label_name = PG_GETARG_NAME(1). Since these two variables are also passed as parameters, I was thinking that, if I wanted to add one more parameter to this function, then I would need to use PG_GETARG_NAME(2) to get this parameter and use it in the function's logic. Is my assumption correct or do I need to do more tweaks to do this?
You are correct, but you also need to change the function signature in the "age--1.2.0.sql" file, updating the arguments:
CREATE FUNCTION ag_catalog.create_vlabel(graph_name name, label_name name, type new_argument)
RETURNS void
LANGUAGE c
AS 'MODULE_PATHNAME';
Note that all arguments come as a "Datum" struct, and PG_GETARG_NAME automatically converts it to a "Name" struct. If you need an argument as int32, for example, you should use PG_GETARG_INT32(index_of_the_argument), for strings, PG_GETARG_CSTRING(n), and so on.
Yes, your assumption is correct. If you want to add an additional parameter to the create_vlabel function in PostgreSQL, you can retrieve the value of the third argument using PG_GETARG_NAME(2). Keep in mind that you may need to make additional modifications to the function's logic to handle the new parameter correctly.
The answers given by Fahad Zaheer and Marco Souza are correct, but you can also create a Variadic function, with which you could have n number of arguments but one drawback is that you would have to check the type yourself. You can find more information here. You can also check many Apache Age functions made this way e.g agtype_to_int2.

kdb/q: apply the function, pass the return value to the function again, multiple rounds

I have a list of symbols, say
`A`B`C
. I have a table tab0; A function that takes in a table plus a string as arguments.
tab1: f[tab0;`A]
tab2: f[tab1;`B]
tab3: f[tab2;`C]
I only care about the final values. But my list of symbols can be long and can have variable length, so I don't want to hardcode above. How do I achieve it?
I think it has something to do with https://code.kx.com/q/ref/accumulators/ but I really struggle to figure out the syntax.
This is exactly the use case for the binary application of over (/) (https://code.kx.com/q/ref/accumulators/#binary-application)
So you should use:
f/[tab0;`A`B`C]

Should I use partial function for database calls

As per my understanding, partial functions are functions that are defined for a subset of input values.
So should I use partial functions for DAO's. For example:
getUserById(userId: Long): User
There is always an input userId which does not exists in db. So can I say it is not defined. And lift it when I call this function.
If yes where do I stop. Should I use partial functions for all methods which are not defined, say for null.
PartialFunction is used when function is undefined for some elements of input data (input data may be Seq etc.)
For your case Option is better choice: it says that return data may be absent:
getUserById(userId:Long):Option[User]
I would avoid using partial functions at all, because scala makes it very easy to call a partial function as though it were a total function. Instead it's better to use a function that returns Option as #Sergey suggests; that way the "partial-ness" is always explicit.
Idiomatic scala does not use null so I wouldn't worry about methods which are not defined for null, but certainly it's worth returning Option for methods which are only defined for some of their possible input values. Better still, though, is to only accept suitable types as input. E.g. if you have a function that's only valid for non-empty lists, it should take (scalaz) NonEmptyList as input rather than List.

How can I make the value of an expression equal to a second return value of another expression

Is there an idiomatic way in Matlab to bind the value of an expression to the nth return value of another expression?
For example, say I want an array of indices corresponding to the maximum value of a number of vectors stored in a cell array. I can do that by
function I = max_index(varargin)
[~,I]=max(varargin{:});
cellfun(#max_index, my_data);
But this requires one to define a function (max_index) specific for each case one wants to select a particular return value in an expression. I can of course define a generic function that does what I want:
function y = nth_return(n,fun,varargin)
[vals{1:n}] = fun(varargin{:});
y = vals{n};
And call it like:
cellfun(#(x) nth_return(2,#max,x), my_data)
Adding such functions, however, makes code snippets less portable and harder to understand. Is there an idiomatic to achieve the same result without having to rely on the custom nth_return function?
This is as far as I know not possible in another way as with the solutions you mention. So just use the syntax:
[~,I]=max(var);
Or indeed create an extra function. But I would also suggest against this. Just write the extra line of code, in case you want to use the output in another function. I found two earlier questions on stackoverflow, which adress the same topic, and seem to confirm that this is not possible.
Skipping outputs with anonymous function in MATLAB
How to elegantly ignore some return values of a MATLAB function?
The reason why the ~ operator was added to MATLAB some versions ago was to prevent you from saving variables you do not need. If there would be a syntax like the one you are searching for, this would not have been necessary.

How can I idiomatically access the first element of a single element hash in Perl?

I have script that gets some data using DBI's fetchall_hashref().
Usually it returns a hash ref like the following:
{ 1 => { id => 1 } }
However, I'm only interested in the value of the first item in the hash, which is the max value of a particular column. I know Perl hashes are not ordered, but luckily this particular query always return exactly 1 or 0 records (since this is a MAX() query).
But the code currently used to achieved that is really ugly:
$results->{(keys %{$results})[0]}->{'id'};
Is there a more elegant way to active this? (Without resorting to CPAN modules)
Clarification
I'm getting the hash from a data access layer that we use in house. Everything gets returned via fetchall_hashref(). I don't call the fetchall_hashref() itself, it's just how the data access functions are implemented internally, so I'm told. I'm a consumer of that returned data and it happens to be in the form of a hash. I'm looking for a more concise way, if it exists, to access the results of single return value queries
You can dereference the id key of the first value in %$results:
(values %$results)[0]->{id};
Normally, this would not be well defined since the ordering of values returned keys or values can be different even between runs on the same machine using the same perl, but since you said %$results can only ever contain one or zero elements, this is a valid method.
Instead of fetchall_hashref if you're only getting 0/1 rows back why not do a selectrow_array or selectrow_hashref?
Why are you using fetchall_hashref to fetch a single value? This is better done using selectrow_array:
my ($max) = $dbh->selectrow_array($sql);
Update: if you can't use another DBI method, a more concise way would be:
my $val = [%$results]->[1]{id};
Does your data access layer always return a hash with sequential keys? If so, then what about
$results->{1}{id}
(Of course, it may not... but your example data used the key 1 for the first record, so it's possible that the data access layer may use deterministic keys.)
my #keys = sort { $a <=> $b } keys %$results;
my $first = $keys[0];
$results->{$first}->{id};
or if $first = 1;
$results->{1}->{id};