2

I have a custom function like this

stringLength[string_] := 
 StringLength[
  ToExpression[StringJoin[ToString /@ {del, string}]] = 
   StringDelete[string, " "]]

I hope when the function return the string's length and set its value to a new symbol simultaneously.But actually this action is forbided in Mathematica

rand = "1 2 3 4 5 6 7 8 9";

Mathematica graphics

So how to implement this demand?


The return is 9 and the delrand is "123456789"(no whitespace) in my expected.


As the @m_goldberg and the @RunnyKine's help,I update my custom function to this

Clear["`*"]
SetAttributes[stringLength, HoldFirst]
stringLength[string_] := 
 StringLength[
  Evaluate[ToExpression["del" <> ToString@Unevaluated[string]]] = 
   StringDelete[string, " "]]
rand = "1 2 3 4 5 6 7 8 9";
{stringLength[rand], delrand} // FullForm

List[9,"123456789"]

And I understand the HoldFirst this time,thanks you both.Don't closing this post please,and this two post have some difference still.That post just change the parameter's value,but my post have also change the parameter itself.Furthermore,there are @m_goldberg and the @RunnyKine's efforts in follow.

yode
  • 26,686
  • 4
  • 62
  • 167

2 Answers2

3

Start by giving your function the HoldFirst Attribute.

SetAttributes[stringLength, {HoldFirst}]

The following should do what you want. Note that the left hand side of Set (=) is not evaluated, so we have to force it to evaluate by using Evaluate:

stringLength[string_] := 
 With[{res = StringDelete[string, " "]}, 
   (Evaluate @ Symbol["del" <> SymbolName[Unevaluated@string]] = res; 
    StringLength @ res)]

Now we can get the desired behavior when we call this function:

rand = "1 2 3 4 5 6 7 8 9";
stringLength[rand]

9

delrand

"123456789"

RunnyKine
  • 33,088
  • 3
  • 109
  • 176
1

This is a somewhat more general but still more concise version of RunnyKine's answer.

SetAttributes[stringLength, {HoldFirst}]
stringLength[s_Symbol, prefix_String] :=
  With[{nowhite = StringDelete[s, Whitespace]}, 
    StringLength[Evaluate[Symbol[prefix <> SymbolName[Unevaluated[s]]]] = nowhite]]

Clear[delrand]; {stringLength[rand, "del"], delrand}

{9, "123456789"}

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
  • Good solution,And we can set a default like prefix_String: "del". – yode Mar 27 '16 at 11:25
  • I'm confuse that why the delrand I get is a Integer? – yode Mar 27 '16 at 11:33
  • @yode. Have you looked at it with FullForm? – m_goldberg Mar 27 '16 at 11:41
  • Ok,when I restart the kernel,that's normal. – yode Mar 27 '16 at 11:50
  • Can you explain that why we should Unevaluated[s] when set the function HoldFirst?In my understanding,the HoldFirst is enough. – yode Mar 27 '16 at 12:15
  • @yode. Well, you are wrong. HoldFirst is only in force at argument evaluation time, which is before the function body is called. Inside the body. s will evaluated normally unless it is protected. If that were not true, then the assignment to nowhite would not work correctly -- it depends on the value of s. – m_goldberg Mar 27 '16 at 12:22