2
$\begingroup$

This question already has an answer here:

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.

$\endgroup$

marked as duplicate by Leonid Shifrin, m_goldberg, RunnyKine, Yves Klett, MarcoB Mar 27 '16 at 22:16

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ what exactly are you trying to achieve? $\endgroup$ – RunnyKine Mar 27 '16 at 8:23
  • $\begingroup$ @RunnyKine When I run my custom function,then "return the string's length and set its value to del<stringname> simultaneously". $\endgroup$ – yode Mar 27 '16 at 8:39
1
$\begingroup$

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"}

$\endgroup$
  • $\begingroup$ Good solution,And we can set a default like prefix_String: "del". $\endgroup$ – yode Mar 27 '16 at 11:25
  • $\begingroup$ I'm confuse that why the delrand I get is a Integer? $\endgroup$ – yode Mar 27 '16 at 11:33
  • $\begingroup$ @yode. Have you looked at it with FullForm? $\endgroup$ – m_goldberg Mar 27 '16 at 11:41
  • $\begingroup$ Ok,when I restart the kernel,that's normal. $\endgroup$ – yode Mar 27 '16 at 11:50
  • $\begingroup$ Can you explain that why we should Unevaluated[s] when set the function HoldFirst?In my understanding,the HoldFirst is enough. $\endgroup$ – yode Mar 27 '16 at 12:15
3
$\begingroup$

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"

$\endgroup$
  • $\begingroup$ Oh,The delrand should be 123456789(no whitespace) $\endgroup$ – yode Mar 27 '16 at 9:21
  • $\begingroup$ Oh,Sorry my English,your answer help me still,But the return is 9 and the delrand is 123456789 in my expected. $\endgroup$ – yode Mar 27 '16 at 9:27
  • $\begingroup$ @yode. See my update $\endgroup$ – RunnyKine Mar 27 '16 at 9:31
  • $\begingroup$ Good job.thanks a lot.:) $\endgroup$ – yode Mar 27 '16 at 9:33
  • $\begingroup$ Sorry,I should give a thought to accept it.Maybe there are better solutions to do this. $\endgroup$ – yode Mar 27 '16 at 9:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.