Passing a method as a parameter in Ruby
Solution 1
You want a proc object:
gaussian = Proc.new do |dist, *args|
sigma = args.first || 10.0
...
end
def weightedknn(data, vec1, k = 5, weightf = gaussian)
...
weight = weightf.call(dist)
...
end
Just note that you can't set a default argument in a block declaration like that. So you need to use a splat and setup the default in the proc code itself.
Or, depending on your scope of all this, it may be easier to pass in a method name instead.
def weightedknn(data, vec1, k = 5, weightf = :gaussian)
...
weight = self.send(weightf)
...
end
In this case you are just calling a method that is defined on an object rather than passing in a complete chunk of code. Depending on how you structure this you may need replace self.send
with object_that_has_the_these_math_methods.send
Last but not least, you can hang a block off the method.
def weightedknn(data, vec1, k = 5)
...
weight =
if block_given?
yield(dist)
else
gaussian.call(dist)
end
end
...
end
weightedknn(foo, bar) do |dist|
# square the dist
dist * dist
end
But it sounds like you would like more reusable chunks of code here.
Solution 2
The comments referring to blocks and Procs are correct in that they are more usual in Ruby. But you can pass a method if you want. You call method
to get the method and .call
to call it:
def weightedknn( data, vec1, k = 5, weightf = method(:gaussian) )
...
weight = weightf.call( dist )
...
end
Solution 3
You can pass a method as parameter with method(:function)
way. Below is a very simple example:
def double(a) return a * 2 end => nil def method_with_function_as_param( callback, number) callback.call(number) end => nil method_with_function_as_param( method(:double) , 10 ) => 20
Solution 4
The normal Ruby way to do this is to use a block.
So it would be something like:
def weightedknn( data, vec1, k = 5 )
foo
weight = yield( dist )
foo
end
And used like:
weightenknn( data, vec1 ) { |dist| gaussian( dist ) }
This pattern is used extensively in Ruby.
Solution 5
You can use the &
operator on the Method
instance of your method to convert the method to a block.
Example:
def foo(arg)
p arg
end
def bar(&block)
p 'bar'
block.call('foo')
end
bar(&method(:foo))
More details at http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
user2018
Updated on July 08, 2022Comments
-
user2018 almost 2 years
I am developing a .NET based web application and I want to connect to a SQL Server, which I created using SQL Server Management Studio 2014. I already followed tutorials from ITWorld and CodeProject with no success. I got an error "Network Path was not found". Although when I test it on Project Properties - > Settings -> Connection Properties, The result is "Test Connection succeeded". Executing Query directly via SQL Management Studio works too.
How do I fix this problem?
Web.config
<connectionStrings> <add name="SQL_Server" connectionString="Data Source=192.168.60.130;Initial Catalog=TestServer;Persist Security Info=True;User ID=name;Password=password" providerName="System.Data.SqlClient" /> </connectionStrings>
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e) { string sqlConn = "SQL_Server"; ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[sqlConn]; using (SqlConnection conn = new SqlConnection(settings.ConnectionString)) { conn.Open(); //this is line 31 as shown from the Stack Trace error below SqlCommand command = new SqlCommand("SELECT * from [SQL_DB].[dbo].[users]", conn); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { Console.WriteLine(reader); } } Console.ReadLine(); Console.Clear(); } }
Stack Trace:
[Win32Exception (0x80004005): The network path was not found] [SqlException (0x80131904): Network-related or instance-specific error when connecting to SQL Server. The server was not found or can not be accessed. Verify that the instance name is correct and that SQL Server allows remote connections. (provider: Named Pipes Provider, error: 40 - Could not open connection with SQL Server)] System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager) +1431 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) +1085 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) +70 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) +964 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) +109 System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) +1529 System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) +156 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) +258 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) +312 System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) +202 System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) +413 System.Data.SqlClient.SqlConnection.Open() +128 VF.BC._Default.Page_Load(Object sender, EventArgs e) in C:\Users\VM_User\source\repos\SQLProject\Default.aspx.cs:31 System.Web.UI.Control.OnLoad(EventArgs e) +106 System.Web.UI.Control.LoadRecursive() +68 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3785
-
Marco Salerno almost 6 yearsTry to give a normal name to the connection string
-
Risto M almost 6 yearsCheck with debugger, what is value of: settings.ConnectionString. Is it the same what you have written in configuration file?
-
user2018 almost 6 years@MarcoSalerno I changed with a shorter name. Still got same error
-
Marco Salerno almost 6 years@User2018 call it "examplename" and try again
-
user2018 almost 6 years@RistoM Yes it's the same
-
user2018 almost 6 years@MarcoSalerno Still the same error.
-
user2018 almost 6 yearsI added the stack trace error
-
Nick.McDermaid almost 6 yearsThis is the part of the error that is useful:
Network-related or instance-specific error when connecting to SQL Server. The server was not found or can not be accessed. Verify that the instance name is correct and that SQL Server allows remote connections. (provider: Named Pipes Provider, error: 40 - Could not open connection with SQL Server)]
-
Nick.McDermaid almost 6 yearsIs the web server, management studio, and the SQL Server all on the same machine? What does I haven't change the Firewall settings because I'm not sure I'm allowed to change them mean? This is a network issue so we need to understand the network situation
-
Nick.McDermaid almost 6 yearsFirst thing to do is change the connection string to force tcp (not names pipes) like this:
Data Source=tcp:192.168.60.130;Initial Catalog=TestServer;Persist Security Info=True;User ID=name;Password=password
. Then you need to ensure the web server can connect to the SQL Server. This is difficult to troubleshoot in this manner. You need to ask an admin at your work to ensure that the web server can connect to the SQL Server
-
-
Alex Wayne over 15 yearsWhen he does
weightf = gaussian
in the arg list it's actually trying to executegaussian
and assign the result as the default value of weightf. The call doesn't have required args and crashes. So weightf is not even a proc object with a call method just yet. -
Jimmy Stenke over 15 yearsI think that second option is the best option (that is, using Object.send()), the drawback is that you need to use a class for all of it (which is how you should do in OO anyway :)). It is more DRY than passing a block (Proc) all the time, and you could even pass arguments trough the wrapper method.
-
xxjjnn over 10 yearsAs an addition, if you want to do
foo.bar(a,b)
with send, it isfoo.send(:bar, a, b)
. The splat (*) operator allows you to dofoo.send(:bar, *[a,b])
should you find you want to have an arbitrary lengthed array of arguments - assuming the bar method can soak them up -
Admin about 10 yearsThis is interesting. It's worth noting that you call
method( :<name> )
just once when converting your method name to a callable symbol. You can store that result in a variable or a parameter and keep passing it to child functions like any other variable from then on... -
Yahya almost 9 yearsOr maybe, instead of using the method syntax in the argument list, you can use it while invoking the method as follows : weightedknn( data, vec1, k, method( :gaussian) )
-
Developer about 8 yearsThis is really bad practice, never do it!
-
danuker about 8 yearsThis method is better than mucking around with a proc or block, since you don't have to handle parameters - it just works with whatever the method wants.
-
medik over 7 yearsFor completion, if you want to pass a method defined somewhere else, do
SomewhereElse.method(:method_name)
. That's pretty cool! -
V. Déhaye over 7 yearsI faced an issue for a method with a more complicated scope, and finally figured out how to do, hope this can help someone : If your method is for example in another class, you should call the last line of code like
method_with_function_as_param(Class.method(:method_name),...)
and notmethod(:Class.method_name)
-
crackpotHouseplant almost 7 yearsThis may be its own question but, how can I determine if a symbol references a function or something else? I tried
:func.class
but that's just asymbol
-
jlesse about 6 years@Developer why is this considered bad practice?
-
Developer almost 6 yearsAmong performance reasons, the
eval
can execute arbitrary code so it is extremely vulnerable to various attacks. -
user2018 almost 6 yearsThe SQL Server is running. I have changed the settings in SQL Server Configuration Manager, but I still got the same error. I haven't change the Firewall settings because I'm not sure I'm allowed to change them.
-
Ihtsham Minhas almost 6 yearsThere is nothing wrong with your code. It should work. Did you try to access using management studio
-
user2018 almost 6 yearsI tried already with SQL management studio and it works too. Test connection via Connection Properties also succeeded.
-
Ihtsham Minhas almost 6 yearsDid you try with port 1433? "Data Source=192.168.60.130, 1433;
-
user2018 almost 6 years@Nick.McDermaid The Web Server and the SQL Server are on different machines (192.168.60.130 and 192.168.60.131). I'm not sure because this is a work project code. Not a personal project.
-
user2018 almost 6 yearsI created the firewall rule and test with port 1433. Now I got an error: The wait operation timed out. I tried also with "MultiSubnetFailover=True".
-
Ihtsham Minhas almost 6 yearsAdd following in connection string Network Library=DBMSSOCN;
-
user2018 almost 6 yearsHi @A to Z Tak, Welcome to StackOverflow! This question was already answered a long time ago. So you might continue contributing on other unanswered questions :). Thank you anyway for your answer! And yes, Firewall was the issue.
-
Raja Jee almost 6 yearsI miss that answer. Thank you for your comment .
-
rmcsharry almost 5 yearsThis (ie. doing it wrong and the comment explaining why) actually allowed me to fully understand the accepted answer, so thanks! +1
-
Ludovic Kuty over 4 yearsThanks to your answer, I discovered the method called
method
. Made my day but I guess that's why I prefer functional languages, no need to make such acrobatics to get what you want. Anyway, I dig ruby