Possible to take generic parameters as arguments in a function?


#1

I am still very new to Rust and have been wondering if there is a way to have a function take in different types of arguments in one args place. Lets say fn fun( a: String) or it could take fn fun( a: Vec<String>) is this possible? Should this even be done if it is possible? And if not what other way could I accomplish this kind of functionality. I need to have a fn that takes in either a tuple or a vector.

One alternative I have thought about is having a tuple that can take either a str or vector. I am trying to make a function that can take a matrix and select specific indexes to extract from the matrix to create a new matrix from. Say a matrix of 11 columns and 4 rows. I want all the rows minus the 1st, and columns 1 and 2. Something like pandas iloc where you get a dataset from a .csv and convert it to a dataframe by copying over the content. So dataset.iloc[:, :-1].values would give me all the rows and all but the last column back as a matrix.


#2

You can do this with an enum with two variants.


#3

Oh nice I forgot about enums. How would I evaluate the type in the function? I have different functionality depending on which type it is.


#4

Just like you would with regular enums: use match.


#5

If the two cases have not much in common, it might be preferable to have two different functions.


#6

@troplin
Well the idea stems from python’s pandas iloc function. if you were to put in dataset.iloc[:,[1,2,4,]] you would get all rows but only columns with index 1,2,4. This is why I would like to take vector. The tuple would be like (i64,str,i64); because in the tuple I can have (,’:’,) wich in the rust version of the iloc function It will look like this. dataset.fnName((,’:’,),vec![1,2,4]), Here I asked for all rows(argument 1) and only columns 1,2, and 4 just like the pandas functionality.

So in short I have to have the functionality of both in the function because the arguments can mix and match. either 2 tuples or 2 vectors or either or. Also the reason for the tuple is to create a range instead of selection. so you could have (1,’:’,3) and get all rows/columns from 1-3 index. Or (,’:’,-1) all rows/columns except the last, (0,’:’,-1) would in a sense do the same.


#7

Since you’re talking about indexing, let me show you how slices in Rust allow indexing by a different types. With a slice (or a vector) you can do:

slice[5] // index by usize
slice[5..] // by RangeFrom
slice[..] // by RangeFull
slice[..5] // by RangeTo

There are two possible solutions to implement this:

  1. Implement a trait multiple times, so impl Index<usize> for ..., impl Index<RangeFrom> for ..., etc. You can also index by tuples (which seems is what you want, the syntax unfortunately be [(a,b)], but that’s just a minor issue). This solution only works for some traits and can’t be used for regular functions (which are not overloadable)
  2. Create another trait (in case of slices it’s SliceIndex), that implements the functionality, and then create a generic impl, like so (this is the implementation for slice):
 impl<T, I> Index<I> for [T] where I: SliceIndex<T>

If you’re not using a trait, but a function, you can easily use 2. solution too by using the same bound.

As you see, you can put almost all the code into this additional trait, like in SliceIndex, but if all your function invocations are going to return the same type, the trait can contain only the helper function and the main logic can still be inside of the function.

Also a few nits: Don’t take : as a string, just use the RangeFull struct (which is created by .. literal). Also, just the &[usize] instead of the Vec would be enough.


#8

Thanks @krdln, that is a lot of useful information. With that I don’t think I will need tuples, I didn’t know you could do a full range in a Rust Vector. I will be having two different matrix datasets. I do have a question for you since you seem to know a lot about vectors. First the purpose then the question. I have a matrix that will be of type Vec<Vec> which will be populated from reading in a .csv file, this is why I needed the index ranges, to make a selection from this matrix to move to a new matrix that is of type Vec<Vec>.

What is the best way to go about that? I am trying to not be wasteful and learn best practices as I work on this. I just am not sure what would be the best choice, a full copy, box the values and move them, or having a mutable reference to each value in the matrix pushed to another matrix. Because I will be working with these extracted matrices to work matrices math on them. I could have several different matrices pulled from many files and need to work with them together depending on data. I also will need to edit them from yes/no toe true/false. Things like this. What is the best way to at least meet some of these categories?


#9

Usually, it’s better to use just flat Vec<T> and index it with row * width + col. Of course, not to do this quite ugly indexing all the time, it’s best to wrap it in some Matrix structure. Which leads to the next thing – unless you’re trying to implement matrices for the learning purposes, just use a library from crates.io that has matrices already implemented. I remember rulinalg (simpler) nad nalgebra (more flexible, but also more compicated), but there are probably more of them.

To avoid unnecessary copying, you usually make the Matrix type, that you create once and keep it alive and something like MatrixView to view different chunks of the original matrix (both immutable and mutable variants).


#10

I am making a Matrix struct. Although I have looked over several dozen matrices libraries they don’t seem to have what I want. The reason I ask how to copy items is I need to pull the data lets say a column of countries with three different countries. I need to break that column up and transform it into 3 separate columns of 1s and 0s, 1s where that country occured. And then later encode those columns with the same range of encoding on the rest of the matrix for euclidian distance reasons.

This is for learning purposes so and am looking to get into the nitty gritty of it all. I am trying to write a lib that accomplishes several things, data preprocessing, accounting for missing data, formatting categorical data, splitting data into training and test sets, and feature scaling. Later I will be adding on new parts for regression techniques and many more machine learning aspects. I am reading data in from a .csv file so I need to have what I would call a master matrix struct that is of type String to hold the retrieved data. And have a separate matrix struct for fitting transformed data from that Master matrix.